数据可视化
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()
- 中位数:盒子中间的线
- 上/下四分位数:盒子上下边缘
- 离群值:落在“胡须”外的点
- 数学成绩
- 中位数最高(约88分),且箱体较短 → 学生成绩集中且整体较好。
- 无异常值 → 无极端高分或低分。
- 语文成绩
- 箱体较长 → 成绩分布较分散(从70分到95分)。
- 上方有一个异常值(95分)→ 可能存在个别高分学生。
- 英语成绩
- 中位数最低(约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()