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风格的有状态的接口,另一个是功能更强大的面向对象接口。
状态接口
折线图
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| python Python import matplotlib.pyplot as plt from matplotlib import rcParams rcParams["font.sans-serif"] = ["SimHei"] #指定中文字体 rcParams["font.sans-serif"] = ['STHeiti'] #mac month = ['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 )
适用场景:
- 对比不同类别的数据大小(如科目成绩、地区销量)
完整代码:
python
Python
import 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()
python
Python
plt.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 )
适用场景:
- 显示整体构成比例(时间分配、市场份额)
完整代码:
python
Python
import matplotlib.pyplot as plt
labels = ['学习', '娱乐', '运动', '睡觉']
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()
|---|
| |
环形图
python
Python
import 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()
爆炸式饼图
python
Python
import 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 )
适用场景:
- 展示两个数值变量之间的关系(相关性)
完整代码:
python
Python
import 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()
python
Python
import matplotlib.pyplot as plt
import 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 )
适用场景:
- 展示数据的分布、极值、中位数、异常值
完整代码:
python
Python
import 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+分)。
- 下方无异常值 → 无极端低分。
面向对象接口
多个图表的绘制
python
Python
import numpy as np
import matplotlib.pyplot as plt # 导入matplotlib
month = ['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()