文章/Matplotlib/第 1 章
概述与安装
Matplotlib · 第 1 / 43 章
504 字约 1 分钟
它在生态里的位置
Matplotlib 是 Python 绘图的事实标准:唯一被几乎所有科学库依赖的绘图库。
两种风格
面向对象风格(OO 风格)
Python12 行
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 200)
y = np.sin(x)
fig, ax = plt.subplots(figsize=(6, 3.5)) # ← OO 风格(推荐):显式拿 Figure 和 Axes
ax.plot(x, y, label='sin')
ax.set_title('正弦') # 输出: 标题落在 Axes 上方
ax.set_xlabel('x'); ax.set_ylabel('y')
ax.legend(); ax.grid(alpha=0.3)
plt.show()- 先显式创建
fig(画布)和ax(坐标轴)。 - 之后所有绘图、设置都通过
ax.xxx()完成。 - 你始终知道自己在操作哪个对象。

等价的 pyplot 风格(状态机风格, 老写法,能跑但不推荐):
Python10 行
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 200)
y = np.sin(x)
plt.plot(x, y, label='sin') # 隐式创建 Figure 和 Axes
plt.title('正弦'); plt.xlabel('x'); plt.ylabel('y')
plt.legend(); plt.grid(alpha=0.3)
plt.show()- 不显式创建,
plt.plot()内部自动创建一个 Figure 和一个 Axes。 - 后续
plt.xxx()都作用于 “当前活动轴”(current axes)。 - 你不直接持有对象引用,全靠 pyplot 内部维护的“当前状态”。
plt.xxx() 在底层其实就是“找到当前活动轴,然后调用它的方法”。
| pyplot 风格 | OO 风格 | 说明 |
|---|---|---|
plt.plot(x, y) |
ax.plot(x, y) |
画线 |
plt.title(...) |
ax.set_title(...) |
标题 |
plt.xlabel(...) |
ax.set_xlabel(...) |
x 轴标签 |
plt.ylabel(...) |
ax.set_ylabel(...) |
y 轴标签 |
plt.legend() |
ax.legend() |
图例 |
plt.grid(...) |
ax.grid(...) |
网格 |
plt.xlim(...) |
ax.set_xlim(...) |
范围 |
plt.show() |
plt.show() |
显示(两者共用) |
note
pyplot 里叫 plt.xxx(),OO 里通常叫 ax.set_xxx()(少数如 legend、grid 名字不变),真正拉开差距的是多子图的情况
多子图差异比较
用 pyplot 风格画两个子图: 能画,但每次都要靠 plt.subplot() 切换“当前活动轴”,切错了就画到别的图上。代码一长非常容易出错。
Python7 行
plt.subplot(1, 2, 1)
plt.plot(x, y)
plt.title("左图")
plt.subplot(1, 2, 2)
plt.plot(x, -y)
plt.title("右图")用 OO 风格画两个子图: axs[0]、axs[1] 是明确的对象,想改哪个就改哪个,不存在“切错轴”的问题。
Python5 行
fig, axs = plt.subplots(1, 2)
axs[0].plot(x, y)
axs[0].set_title("左图")
axs[1].plot(x, -y)
axs[1].set_title("右图")figsize 的指定
- OO 风格:
plt.subplots(figsize=(6, 3.5)),创建时就指定。 - pyplot 风格:只能
plt.figure(figsize=(6, 3.5))额外加一行。
保存图片
OO 风格:fig 就在手里,直接存。
Python1 行
fig.savefig("out.png", dpi=300, bbox_inches="tight")pyplot 风格:需要依赖“当前活动 Figure”,在复杂程序里容易存错。
Python1 行
plt.savefig("out.png", dpi=300, bbox_inches="tight")拿到 Figure / Axes 对象
- OO 风格:一开始就拿到了,随时用。
- pyplot 风格:要用
plt.gcf()(get current figure)、plt.gca()(get current axes)去取
函数封装
Python8 行
# OO 风格:把 ax 当参数传,函数能画到任意轴上
def plot_sin(ax, x):
ax.plot(x, np.sin(x))
ax.set_title("sin")
fig, axs = plt.subplots(2, 1)
plot_sin(axs[0], x)
plot_sin(axs[1], x)pyplot 风格做不到这种干净的复用,函数里只能靠“当前活动轴”,外界无法控制它画到哪。
与 seaborn 配合
seaborn 的轴级函数(如 sns.boxplot)返回的是 Axes
Python3 行
g = sns.boxplot(data=df, x='day', y='total_bill')
g.set_title('消费分布')
g.tick_params(axis='x', labelrotation=45)如果用 pyplot 风格,就只能写 plt.title(...),依赖“当前活动轴”。
以下笔记都基于 OO 风格
中文显示
Python14 行
import matplotlib as mpl
import matplotlib.pyplot as plt
# 方案 A:全局设置(最常用)
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei'] # 按优先级找
plt.rcParams['axes.unicode_minus'] = False # 必须!否则负号变方框
# 方案 B:局部(不污染全局)
with mpl.rc_context({'font.sans-serif': ['Microsoft YaHei'], 'axes.unicode_minus': False}):
fig, ax = plt.subplots(); ax.set_title('中文标题'); ax.plot([1, 2, 3])
# 方案 C:单个对象
fig, ax = plt.subplots()
ax.set_title('中文', fontfamily='Microsoft YaHei')