Matplotlib 完整教程:从入门到精通
目录
-
(图片来源网络,侵删)- 什么是 Matplotlib?
- 为什么选择 Matplotlib?
- Matplotlib 的核心架构
-
- 安装 Matplotlib
- 导入库
- 绘制你的第一个图:
plt.plot() - 显示与保存图片:
plt.show()和plt.savefig()
-
- 三层架构:
Artist层 - 关键对象:
Figure和Axes pyplot与AxesAPI 的关系- 重要:推荐使用
AxesAPI
- 三层架构:
-
- 折线图 (
plot) - 散点图 (
scatter) - 柱状图 (
bar,barh) - 直方图 (
hist) - 饼图 (
pie) - 箱线图 (
boxplot) - 热力图 (
imshow)
- 折线图 (
-
(图片来源网络,侵删)- 和标签 (
set_title,set_xlabel,set_ylabel) - 设置图例 (
legend) - 设置坐标轴范围 (
set_xlim,set_ylim) - 设置网格 (
grid) - 设置文本 (
text,annotate) - 设置样式 (
style) - 调整布局 (
tight_layout)
- 和标签 (
-
- 子图 (
subplotvssubplots) - 绘制双轴 (
twinx,twiny) - 绘制误差线 (
errorbar) - 处理日期数据
- 使用 Seaborn 进行高级美化
- 子图 (
-
- 常见问题
- 学习资源推荐
第一部分:Matplotlib 简介
什么是 Matplotlib?
Matplotlib 是 Python 中最著名、最基础的数据可视化库,它功能强大,高度可定制,可以生成从简单的折线图到复杂的科学图表在内的各种静态、动态和交互式图表。
为什么选择 Matplotlib?
- 历史悠久,社区庞大:几乎所有 Python 数据科学相关的教程和书籍都会使用 Matplotlib,遇到问题很容易找到解决方案。
- 功能全面:几乎涵盖了所有常见的图表类型,并且提供了极其精细的控制能力。
- 可定制性极强:从字体、颜色、线型到布局,几乎所有元素都可以修改。
- 与其他库无缝集成:是 NumPy、Pandas、SciPy 等科学计算库的默认可视化工具。
Matplotlib 的核心架构
理解 Matplotlib 的三层架构对于深入学习至关重要:
- 后端层:负责将图表渲染成具体的格式(如 PNG, SVG, PDF),用户通常不需要直接接触这一层。
Artist层:这是 Matplotlib 的核心。Artist对象是图表的“画笔”和“画布”,所有可见的元素(如Figure,Axes,Line2D,Text等)都是Artist的子类,通过操作Artist对象,我们可以精确地控制图表的每一个细节。- 脚本层 (
pyplot):这是我们最常使用的接口。pyplot提供了一组类似 MATLAB 的函数,可以方便地快速绘图,它实际上是Artist层的一个简化封装,自动处理了创建Figure和Axes等繁琐工作。
第二部分:环境准备与基础绘图
安装 Matplotlib
如果你已经安装了 Anaconda,Matplotlib 通常已经包含在内,如果没有,可以通过 pip 安装:
pip install matplotlib
导入库
通常我们这样导入:
import matplotlib.pyplot as plt import numpy as np # 经常与 NumPy 一起使用
绘制你的第一个图:plt.plot()
plt.plot() 是最简单的绘图函数,它会自动将数据点连接成线。
# 准备数据 x = np.linspace(0, 10, 100) # 0到10之间生成100个点 y = np.sin(x) # 绘制正弦曲线 plt.plot(x, y) # 显示图片 plt.show()
运行这段代码,你会弹出一个窗口显示一个漂亮的正弦波。
显示与保存图片
- 显示图片:
plt.show()会暂停程序,显示图表窗口,在 Jupyter Notebook 或类似环境中,plt.plot()会自动显示。 - 保存图片:
plt.savefig()可以将图表保存为文件。plt.plot(x, y) plt.savefig('sine_wave.png', dpi=300, bbox_inches='tight') # 保存为PNG,300dpi,并裁剪掉多余部分
第三部分:深入理解 Matplotlib 架构
关键对象:Figure 和 Axes
这是从“会画”到“画好”的关键一步。
Figure(画布):是整个图表的顶级窗口或容器,你可以把它想象成一个画板,上面可以放置一个或多个图表。Axes(坐标系/子图):是Figure上的一个绘图区域,也就是我们通常所说的“图表”,一个Figure可以包含多个Axes,每个Axes都有自己的坐标轴、标题、标签等。
pyplot 与 Axes API 的关系
pyplot 会自动跟踪当前的 Figure 和 Axes,当你调用 plt.plot(x, y) 时,pyplot 会:
- 检查是否存在当前的
Figure和Axes。 - 如果不存在,就创建一个新的
Figure和Axes。 - 然后在当前的
Axes上调用plot方法。
重要:推荐使用 Axes API
虽然 pyplot 方便,但当你需要在一张画布上画多个图,或者需要对图表进行复杂定制时,直接使用 Axes API 会更清晰、更强大。
# pyplot API (简单但难以管理复杂图表)
plt.figure(figsize=(8, 4))
plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x))'Pyplot API')
plt.show()
# Axes API (推荐,更清晰、更强大)
fig, ax = plt.subplots(figsize=(8, 4)) # 创建一个Figure和一个Axes
ax.plot(x, np.sin(x), label='sin(x)')
ax.plot(x, np.cos(x), label='cos(x)')
ax.set_title('Axes API')
ax.set_xlabel('x-axis')
ax.set_ylabel('y-axis')
ax.legend() # 添加图例
plt.show()
对比:Axes API 中,所有命令都是通过 ax 对象调用的(如 ax.plot, ax.set_title),这明确指出了操作的目标,避免了混淆。
第四部分:常用图表类型详解
折线图 (plot)
用于展示数据随时间或某个连续变量的变化趋势。
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4], [1, 4, 2, 3], marker='o', linestyle='--', color='g')
ax.set_title('折线图示例')
plt.show()
散点图 (scatter)
用于展示两个变量之间的关系。
np.random.seed(0)
x = np.random.rand(50)
y = np.random.rand(50)
colors = np.random.rand(50)
sizes = 1000 * np.random.rand(50)
fig, ax = plt.subplots()
scatter = ax.scatter(x, y, c=colors, s=sizes, alpha=0.5, cmap='viridis')
ax.set_title('散点图示例')
fig.colorbar(scatter, ax=ax, label='颜色映射') # 添加颜色条
plt.show()
柱状图 (bar, barh)
用于比较不同类别的数据。
categories = ['A', 'B', 'C', 'D']
values = [15, 30, 45, 10]
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) # 创建1行2列的子图
# 垂直柱状图
ax1.bar(categories, values, color='skyblue')
ax1.set_title('垂直柱状图')
# 水平柱状图
ax2.barh(categories, values, color='salmon')
ax2.set_title('水平柱状图')
plt.tight_layout()
plt.show()
直方图 (hist)
用于展示数据的分布情况。
data = np.random.normal(0, 1, 1000) # 生成1000个标准正态分布的随机数
fig, ax = plt.subplots()
ax.hist(data, bins=30, color='purple', alpha=0.7, edgecolor='black')
ax.set_title('直方图示例')
ax.set_xlabel('值')
ax.set_ylabel('频数')
plt.show()
饼图 (pie)
用于展示各部分占总体的比例。
sizes = [30, 20, 45, 5]
labels = ['Python', 'Java', 'C++', 'Other']
explode = (0.1, 0, 0, 0) # 突出显示第一块
fig, ax = plt.subplots()
ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True, startangle=90)
ax.axis('equal') # 保证饼图是圆的
ax.set_title('编程语言使用比例')
plt.show()
箱线图 (boxplot)
用于展示一组数据的分布情况,包括中位数、四分位数和异常值。
data = np.random.normal(0, 1, (100, 4)) # 生成4组数据
labels = ['Group A', 'Group B', 'Group C', 'Group D']
fig, ax = plt.subplots()
ax.boxplot(data, labels=labels)
ax.set_title('箱线图示例')
plt.show()
热力图 (imshow)
用于展示矩阵数据,颜色深浅代表数值大小。
# 生成一个随机矩阵
data = np.random.rand(10, 10)
fig, ax = plt.subplots()
cax = ax.imshow(data, cmap='coolwarm')
fig.colorbar(cax, ax=ax, label='数值大小')
ax.set_title('热力图示例')
plt.show()
第五部分:图表美化与定制
使用 Axes API 的 set_* 方法进行定制。
# 生成数据
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
# 创建图表和坐标系
fig, ax = plt.subplots(figsize=(10, 6))
# 绘制曲线
ax.plot(x, y1, label='sin(x)', color='blue', linestyle='-', linewidth=2)
ax.plot(x, y2, label='cos(x)', color='red', linestyle='--', linewidth=2)
# 1. 设置标题和标签
ax.set_title('正弦和余弦函数', fontsize=16, pad=20) # pad是标题与图表的间距
ax.set_xlabel('X轴 (弧度)', fontsize=12)
ax.set_ylabel('Y轴', fontsize=12)
# 2. 设置坐标轴范围
ax.set_xlim([0, 10])
ax.set_ylim([-1.5, 1.5])
# 3. 设置网格
ax.grid(True, linestyle=':', which='both', alpha=0.5) # which='both'同时显示主次网格线
# 4. 设置图例
ax.legend(loc='upper right', fontsize=10) # loc可以指定位置
# 5. 设置文本
ax.text(5, 1.2, '最大值点', ha='center') # ha是水平对齐方式
# 6. 调整布局,防止标签被截断
plt.tight_layout()
# 显示图片
plt.show()
设置样式
可以使用 plt.style.context 来临时应用一种预设的样式,让图表更美观。
with plt.style.context('seaborn-v0_8-whitegrid'):
fig, ax = plt.subplots()
ax.plot(x, np.sin(x))
ax.plot(x, np.cos(x))
plt.show()
其他常用样式:'ggplot', 'fivethirtyeight', 'bmh'。
第六部分:进阶技巧
子图 (subplot vs subplots)
plt.subplots() 是创建子图最推荐的方式。
# 创建一个 2x2 的子图网格
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# axes 是一个 NumPy 数组,可以通过索引访问每个子图
axes[0, 0].plot(x, np.sin(x))
axes[0, 0].set_title('子图 1: sin(x)')
axes[0, 1].plot(x, np.cos(x))
axes[0, 1].set_title('子图 2: cos(x)')
axes[1, 0].bar(['A', 'B', 'C'], [3, 7, 2])
axes[1, 0].set_title('子图 3: 柱状图')
axes[1, 1].hist(np.random.randn(100), bins=15)
axes[1, 1].set_title('子图 4: 直方图')
plt.tight_layout()
plt.show()
绘制双轴
当两个数据序列的量纲不同时,双轴非常有用。
fig, ax1 = plt.subplots(figsize=(10, 6))
# 第一个 Y 轴
ax1.plot(x, np.sin(x), 'b-', label='sin(x)')
ax1.set_xlabel('X轴')
ax1.set_ylabel('sin(x)', color='b')
ax1.tick_params(axis='y', labelcolor='b')
# 创建第二个 Y 轴,共享 X 轴
ax2 = ax1.twinx()
ax2.plot(x, np.cos(x) * 10, 'r--', label='cos(x) * 10') # 乘以10以匹配量纲
ax2.set_ylabel('cos(x) * 10', color='r')
ax2.tick_params(axis='y', labelcolor='r')
fig.suptitle('双轴图示例')
plt.show()
绘制误差线
x = np.arange(10)
y = 2.5 * x + 10
error = np.random.rand(10) * 5 # 随机误差
fig, ax = plt.subplots()
ax.errorbar(x, y, yerr=error, fmt='-o', capsize=5, capthick=2, ecolor='red')
ax.set_title('误差线示例')
plt.show()
第七部分:总结与最佳实践
常见问题
- 中文显示乱码:在绘图前,设置一个支持中文的字体。
import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] # 'SimHei' 是黑体,你也可以用 'Microsoft YaHei' 等 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
- 图片显示不清晰:使用
plt.savefig时,设置dpi(dots per inch) 参数,如dpi=300。 - 坐标轴标签被截断:在保存或显示前调用
plt.tight_layout()。
学习资源推荐
- 官方文档:Matplotlib Official Documentation (最权威,但内容较多)
- 教程:Matplotlib Tutorials (官方提供的分步教程)
- 示例库:Matplotlib Gallery (寻找灵感,看懂代码就能学会)
- 书籍:《Python for Data Analysis》 by Wes McKinney (作者也是 Pandas 的作者,其中对 Matplotlib 有很好的介绍)。
希望这份详尽的教程能帮助你从零开始,逐步精通 Matplotlib!祝你绘图愉快!
