> 技术文档 > 数据可视化

数据可视化

4.1  可视化介绍

为什么要进行数据可视化?

  • 数据可视化 = 把抽象的数据“看得见”
  • 目的是让数据背后的规律、异常、趋势一目了然

 错误案例举例:

  • 饼图太多分块 → 看不出比例
  • 柱状图颜色混乱 → 无法聚焦
  • 图表标题模糊不清 → 不知图中所指

4.2  Matplotlib可视化

4.2.1  Matplotlib简介

什么是Matplotlib

Matplotlib是一个Python绘图库,广泛用于创建各种类型的静态、动态和交互式图表。它是数据科学、机器学习、工程和科学计算领域中常用的绘图工具之一。

  • 支持多种图表类型:折线图(Line plots)、散点图(Scatter plots)、柱状图(Bar charts)、直方图(Histograms)、饼图(Pie charts)、热图(Heatmaps)、箱型图(Box plots)、极坐标图(Polar plots)、3D图(3D plots,配合 mpl_toolkits.mplot3d)。
  • 高度自定义:允许用户自定义图表的每个部分,包括标题、轴标签、刻度、图例等。        支持多种颜色、字体和线条样式。提供精确的图形渲染控制,如坐标轴范围、图形大小、字体大小等。
  • 兼容性:与NumPy、Pandas等库紧密集成,特别适用于绘制基于数据框和数组的数据可视化。可以输出到多种格式(如PNG、PDF、SVG、EPS等)。
  • 交互式绘图:在Jupyter Notebook 中,Matplotlib支持交互式绘图,可以动态更新图表。支持图形缩放、平移等交互操作。
  • 动态图表:可以生成动画(使用FuncAnimation类),为用户提供动态数据的可视化。

不同开发环境下显示图形

  • 在一个脚本文件中使用Matplotlib,那么显示图形的时候必须使用plt.show()。
  • 在Notebook中使用Matplotlib,运行命令之后在每一个Notebook的单元中就会直接将PNG格式图形文件嵌入在单元中。

4.2.2 两种画图接口

Matplotlib有两种画图接口:一个是便捷的MATLAB风格的有状态的接口,另一个是功能更强大的面向对象接口。

状态接口

折线图

Pythonimport matplotlib.pyplot as pltfrom matplotlib import rcParamsrcParams[\"font.sans-serif\"] = [\"SimHei\"] #指定中文字体rcParams[\"font.sans-serif\"] = [\'STHeiti\']  #macmonth = [\'1月\',\'2月\',\'3月\',\'4月\']sales = [100,150,80,130]# 创建图表,并设置大小plt.figure(figsize=(10,6))# 绘制折线图plt.plot(month, sales,         label=\'产品A\',         color=\'orange\',         linewidth=2,         linestyle=\'--\',         marker=\'o\',)# 添加标题plt.title(\"2025年销售趋势\",fontsize=16,color=\'red\')# 添加坐标轴的标签plt.xlabel(\'月份\',fontsize=12)plt.ylabel(\'销售额(万元)\',fontsize=12)# 添加图例plt.legend(loc=\'upper left\')# 添加网格线plt.grid(True,alpha=0.1,color=\'blue\',linestyle=\'--\')# grid(axis=\'x\' axis=\'y\'# 自定义刻度字体大小plt.xticks(rotation=0,fontsize=10)plt.yticks(rotation=0,fontsize=10)# 自定义y轴范围plt.ylim(0,200)# 在每个数据点上方添加数值标签for xi, yi in zip(month, sales):    plt.text(xi, yi + 1.5, str(yi), ha=\'center\',fontsize=10)  # ha: 水平对齐方式# 自动优化排版plt.tight_layout()# 显示图表plt.show()

条形图(Bar Chart

适用场景:

  • 对比不同类别的数据大小(如科目成绩、地区销量)

 完整代码:

Pythonimport matplotlib.pyplot as plt# 类别与对应数值subjects = [\'语文\', \'数学\', \'英语\', \'科学\']scores = [85, 92, 78, 88]# 创建条形图plt.figure(figsize=(8, 5))plt.bar(subjects, scores, color=\'skyblue\', width=0.6)# 添加图表元素plt.title(\"学生各科成绩对比\", fontsize=14)plt.xlabel(\"科目\")plt.ylabel(\"分数\")plt.ylim(0, 100)  # 设置y轴范围plt.grid(axis=\'y\', linestyle=\'--\', alpha=0.6)# 为每个柱形添加数值标签for i, score in enumerate(scores):    plt.text(i, score + 1, str(score), ha=\'center\', fontsize=10)plt.tight_layout()plt.show()
Pythonplt.barh(month,sales,        label=\'AI眼镜\',        color=\'orange\',        )        # 长标签场景(条形图更合适)countries = [\'United States\', \'China\', \'Japan\', \'Germany\', \'India\']gdp = [25, 18, 5, 4, 3]plt.barh(countries, gdp, color=\'lightgreen\')plt.title(\'各国GDP对比(单位:万亿美元)\')# plt.tight_layout()  # 自动调整标签间距plt.show()

饼图(Pie Chart

适用场景:

  • 显示整体构成比例(时间分配、市场份额)

完整代码:

Pythonimport matplotlib.pyplot as pltlabels = [\'学习\', \'娱乐\', \'运动\', \'睡觉\']time_spent = [4, 2, 1, 8]# 创建饼图plt.figure(figsize=(6, 6))plt.pie(time_spent,        labels=labels,        autopct=\'%.1f%%\',         # 显示百分比        startangle=90,             # 起始角度        colors=[\'#66b3ff\',\'#99ff99\',\'#ffcc99\',\'#ff9999\'])plt.title(\"一天的时间分配\", fontsize=14)plt.show()

环形图

Pythonimport matplotlib.pyplot as plt# 数据labels = [\'学习\', \'娱乐\', \'运动\', \'睡觉\']time_spent = [4, 2, 1, 8]colors = [\'#ff9999\', \'#66b3ff\', \'#99ff99\', \'#ffcc99\']# 绘制环形图plt.figure(figsize=(8, 6))plt.pie(time_spent, labels=labels, colors=colors,        wedgeprops={\'width\': 0.5},  # 控制环的宽度(0.3~0.7)        autopct=\'%.1f%%\', pctdistance=0.85)  # pctdistance调整百分比位置plt.title(\'环形图\', fontsize=15)# 在中心添加文字plt.text(0, 0, \"总计\\n100%\", ha=\'center\', va=\'center\', fontsize=12)plt.show()

爆炸式饼图

Pythonimport matplotlib.pyplot as plt# 数据labels = [\'学习\', \'娱乐\', \'运动\', \'睡觉\']time_spent = [4, 2, 1, 8]colors = [\'#ff9999\', \'#66b3ff\', \'#99ff99\', \'#ffcc99\']explode = (0.1, 0, 0, 0)  # 仅突出第一块# 绘制爆炸式饼图plt.figure(figsize=(6, 6))plt.pie(time_spent, explode=explode, labels=labels, colors=colors,        autopct=\'%.1f%%\', shadow=True, startangle=90)plt.title(\'爆炸式饼图\', fontsize=15)plt.show()

散点图(Scatter Plot

适用场景:

  • 展示两个数值变量之间的关系(相关性)

完整代码:

Pythonimport matplotlib.pyplot as plt# 模拟数据:学习时间与成绩study_hours = [1, 2, 3, 4, 5, 6, 7]scores = [50, 55, 65, 70, 78, 85, 90]plt.figure(figsize=(7, 5))plt.scatter(study_hours, scores, color=\'green\', s=60)plt.title(\"学习时间与成绩的关系\")plt.xlabel(\"每天学习小时数\")plt.ylabel(\"成绩\")plt.grid(True)# 添加数据点注释(可选)for i in range(len(study_hours)):    plt.text(study_hours[i]+0.1, scores[i], f\"{scores[i]}\", fontsize=9)plt.show()
Pythonimport matplotlib.pyplot as pltimport random  # 仅用Python内置库生成随机数# 1. 生成1000个随机点(模拟正相关数据)random.seed(42)x = [random.uniform(0, 10) for _ in range(1000)]  # X值:0~10均匀分布y = [xi * 2 + random.gauss(0, 2) for xi in x]     # Y值:2倍X值 + 高斯噪声# 2. 绘制散点图plt.figure(figsize=(10, 6))plt.scatter(    x,                   # X轴坐标数据    y,                   # Y轴坐标数据    color=\'blue\',        # 点的填充颜色为蓝色    alpha=0.5,           # 透明度为50%(半透明)    s=20,                # 点的大小为20平方磅    edgecolors=\'none\',   # 点边缘无颜色(无边框)    label=\'数据点\'       # 图例中显示的标签文本)#绘制回归线plt.plot([0, 10],         [0,20],         color=\'red\', linestyle=\'--\', linewidth=2,         label=f\'回归线: y = {slope:.2f}x + {intercept:.2f}\')# 4. 美化图表plt.title(\'1000个随机点的散点图\', fontsize=14)plt.xlabel(\'X轴:自变量\', fontsize=12)plt.ylabel(\'Y轴:因变量\', fontsize=12)plt.grid(True, linestyle=\'--\', alpha=0.3)plt.legend()plt.tight_layout()plt.show()

箱线图(Boxplot

适用场景:

  • 展示数据的分布、极值、中位数、异常值

完整代码:

Pythonimport matplotlib.pyplot as plt# 模拟 3 门课的成绩data = {    \'语文\': [82, 85, 88, 70, 90, 76, 84, 83, 95],    \'数学\': [75, 80, 79, 93, 88, 82, 87, 89, 92],    \'英语\': [70, 72, 68, 65, 78, 80, 85, 90, 95]}plt.figure(figsize=(8, 6))plt.boxplot(data.values(), labels=data.keys())plt.title(\"各科成绩分布(箱线图)\")plt.ylabel(\"分数\")plt.grid(True, axis=\'y\', linestyle=\'--\', alpha=0.5)plt.show()
  • 中位数:盒子中间的线
  • 上/下四分位数:盒子上下边缘
  • 离群值:落在“胡须”外的点
  1. 数学成绩
  • 中位数最高(约88分),且箱体较短 → 学生成绩集中且整体较好。
  • 无异常值 → 无极端高分或低分。
  1. 语文成绩
  • 箱体较长 → 成绩分布较分散(从70分到95分)。
  • 上方有一个异常值(95分)→ 可能存在个别高分学生。
  1. 英语成绩
  • 中位数最低(约78分),但箱须向上延伸较长 → 部分学生成绩较高(90+分)。
  • 下方无异常值 → 无极端低分。

面向对象接口

多个图表的绘制

Pythonimport numpy as npimport matplotlib.pyplot as plt # 导入matplotlibmonth = [\'1月\',\'2月\',\'3月\',\'4月\']sales = [100,150,80,130]fig, ax = plt.subplots(2,2, figsize=(10, 10)) # 创建画布,并指定画布大小# 绘制柱状图ax[0][0].bar(month,sales,        label=\'AI眼镜0\',        color=\'orange\',        width=0.6,)ax[0][1].plot(month,sales,        label=\'AI眼镜1\',        color=\'orange\',        )ax[1][0].bar(month,sales,        label=\'AI眼镜2\',        color=\'orange\',        width=0.6,)ax[1][1].bar(month,sales,        label=\'AI眼镜3\',        color=\'orange\',        width=0.6,)# 添加标题ax[0][0].set_title(\"2025年销售趋势\",fontsize=16,color=\'red\')ax[1][0].set_title(\"2025年销售趋势\",fontsize=16,color=\'red\')# 添加坐标轴的标签ax[0][0].set_xlabel(\'月份\',fontsize=12)ax[0][0].set_ylabel(\'销售额(万元)\',fontsize=12)# 添加图例ax[0][0].legend(loc=\'upper left\')# 添加网格线ax[0][0].grid(True,alpha=0.1,color=\'blue\',linestyle=\'--\')# grid(axis=\'x\' axis=\'y\'# 自定义y轴范围ax[0][0].set_ylim(0,200)plt.show()