大家好,我是你们的小帅学长。
如果你已经能跑通、能保存、中文字体也不炸了,恭喜你:你已经超过了很多“只会复制代码”的阶段。
从这一篇开始,我们要进入真正的核心——Matplotlib 的对象逻辑。
我见过太多同学的画图状态是这样的:
图例一会儿在这,一会儿在那;
子图越画越乱,改一个地方影响另一张;
保存出来不是缺标题就是裁切;
写到后面plt.xxx一堆,自己也不知道哪句在控制哪张图。
这些问题的根源往往不是你不会用函数,而是你没搞清楚:
Figure和Axes到底是什么关系?你到底在改谁?
01.先用一句话讲清楚:Figure 是画布,Axes 是画图的地方
在 Matplotlib 里,你可以把画图理解成“在画布上摆放画框”:
Figure(画布):整张图片的“外层容器”,决定整张图的大小、分辨率、全局布局。
Axes(坐标轴/子图):真正画线、画点、画柱子的地方;标题、坐标、图例等大多数元素都属于 Axes。
所以你以后看到这句:
它就是在说:给我一张画布(fig),同时在画布上放一个画图区域(ax)。
当你需要多个子图时:
fig, axes = plt.subplots(2, 2)
这个意思就是:一张画布上放四个 Axes(四个小画框)。
02.一张图:Figure-Axes 最小可运行模板
下面这段代码你可以直接当作你以后所有静态图的“基础骨架”。
(注意:图片保存为JPG,我这里按期刊常见的要求来写)
import numpy as npimport matplotlib.pyplot as plt
# 1) 准备数据
x = np.linspace(0, 10, 200)y = np.sin(x)
# 2) 创建 Figure + Axes
fig, ax = plt.subplots(figsize=(6, 4))
# 3) 画图(在ax上画)
ax.plot(x, y, linewidth=2)ax.set_title("Figure & Axes Demo")ax.set_xlabel("x")ax.set_ylabel("sin(x)")ax.grid(alpha=0.3)
# 4) 保存为JPG格式
fig.savefig("fig_axes_demo.jpg", dpi=300, bbox_inches="tight")plt.close(fig)
你需要记住:
画图用ax.xxx;
保存用fig.savefig;
保存完plt.close(fig),避免堆图和内存问题。
03.多子图不乱的关键:你拿到的是“axes 数组”
科研里最常见的需求之一:一张图里放多个子图
import numpy as npimport matplotlib.pyplot as pltx = np.linspace(0, 10, 200)fig, axes = plt.subplots(1, 2, figsize=(10, 4), sharey=True)axes[0].plot(x, np.sin(x))axes[0].set_title("sin")axes[1].plot(x, np.cos(x))axes[1].set_title("cos")for ax in axes:ax.set_xlabel("x")ax.grid(alpha=0.3)axes[0].set_ylabel("value")fig.savefig("subplots_demo.jpg", dpi=300, bbox_inches="tight")plt.close(fig)
这里你要抓住一个核心点:
axes 不是一个轴,而是一组轴(数组/列表)。
你必须对每个 ax 分别设置标题、坐标、网格,才会整齐一致。
我把这篇浓缩成一句学习口诀:
Figure 管整体(画布、布局、保存),Axes 管局部(画什么、标题、坐标、图例)。画图写 ax,保存写fig。
搞懂Figure 和 Axes,你就从“能画图”迈进了“能稳定画出一套图”——而科研最需要的,恰恰是这种稳定性。
下一篇我会继续沿着面向对象写法,把“最常用的控制项”一次讲清:
《推荐写法:面向对象(OO)画图模板》
重点是:怎么把你每次都会用的设置(字体、网格、刻度、保存参数)封装成一个可复用模板,以后画任何图都从模板出发。
—期待你的关注—