本章只做一件事:用 matplotlib 把一组数字画成图。看懂了 Figure、Axes 与 add_subplot 三者的关系,后面所有图表——柱形图、饼图、散点图——都只是换了画法,骨架完全一致。
matplotlib 把“画图”拆成了三个层次的对象。教材代码里的 fig 与 ax,
对应的正是最外层的画布与内部的坐标系。
一张完整的图片,可容纳多个坐标系,有尺寸与背景色。
真正承载曲线、柱形、刻度和标题的区域,一张画布上可以有多个。
曲线、点、文字等具体图形元素,都挂在某个 Axes 上。
第 1 章的两个示例都遵循同一顺序。先导入库,再准备数据,然后创建画布与坐标系,最后调用 plt.show() 显示。 任何一张 matplotlib 图表,都可以套进这个模板。
%pip 魔法命令,保证包装进当前内核:
%pip install numpy --disable-pip-version-check
%pip install matplotlib --disable-pip-version-check
先建画布 fig,再在画布上添加坐标系 ax,所有绘制动作都作用在 ax 上。
这是控制力最强、最适合多子图的方式。
import numpy as np
import matplotlib.pyplot as plt
data = np.array([1, 2, 3, 4, 5]) # 准备数据
fig = plt.figure() # 创建代表画布的 Figure 类的对象 fig
ax = fig.add_subplot(223) # 在画布 fig 上添加坐标系风格的绘图区域 ax
ax.plot(data) # 绘制图表
plt.show() # 展示图表
add_subplot(223) 的三个数字不是随便写的:前两位 2、2
表示把画布切成 2 行 2 列,第三位 3 表示使用
按行优先编号的第 3 格——即左下角。其余三格留白,所以图片看起来 “空出了一大块”。
若只想要一张铺满画布的图,把参数写成 111 即可:1 行 1 列第 1 格,
这与直接调用 plt.plot() 的默认效果一致。
点击下面 2×2 网格中的任意一格,看 add_subplot 的参数如何随之变化。
编号规则是 先从左到右,再从上到下。
第 3 格:2 行 2 列中的左下角。这也是教材示例的位置,因此运行时图表偏左下。
pyplot 模块会自动维护“当前画布”和“当前坐标系”,因此可以省略 fig 与 ax,
一行 plt.plot(data) 直接出图。适合快速验证与单图场景。
import numpy as np
import matplotlib.pyplot as plt # 导入 pyplot 模块
data = np.array([1, 2, 3, 4, 5]) # 准备数据
plt.plot(data) # 在当前画布的绘图区域中绘制图表
plt.show() # 展示图表
注意两次运行的差异:数据完全相同,画法完全相同,但前者图表只占左下 1/4 面积。
差别不在数据,而在 add_subplot 给出的位置参数。这正是本章要建立的空间感。
| 对比项 | 面向对象方式 | pyplot 方式 |
|---|---|---|
| 核心语句 | fig = plt.figure()ax = fig.add_subplot(223)ax.plot(data) |
plt.plot(data) |
| 绘制对象 | 明确作用于某个 Axes,可分别控制每个子图 | 作用于“当前” Axes,由 pyplot 隐式维护 |
| 多子图支持 | 强,一张画布可放 2×2、2×3 等布局 | 需配合 plt.subplot(),控制较弱 |
| 代码量 | 略多,但结构清晰 | 最少,适合快速出图 |
| 适用场景 | 正式图表、多图对比、精细化调整 | 探索性分析、单图、教学演示 |
忘记 plt.show()。在脚本文件中运行若没有这句话,图只存在于内存,窗口不会弹出; 在 Jupyter 中末尾不写也能显示,但教材保留该句以保证脚本与笔记本行为一致。
默认画布是 640×480 像素。未设置 figsize 时,matplotlib 采用 6.4×4.8 英寸、
100 dpi,即 640×480。看到图偏小或偏方,属正常现象,可通过 figsize=(8, 5) 调整。
把 add_subplot 的参数当成坐标。223 是 2 行 2 列第 3 格,
不是 x=2、y=2、编号 3 的坐标。写成 231 则是 2 行 3 列的第 1 格,图形会变窄。
中文标题显示为方框。matplotlib 默认字体不含中文字形,需在绘图前设置
plt.rcParams['font.sans-serif'] = ['SimHei'],并关闭负号乱码
plt.rcParams['axes.unicode_minus'] = False。第 4 章会系统讲解字体设置。