目录3

文章Matplotlib第 1 章

概述与安装

Matplotlib · 第 1 / 43 章

它在生态里的位置

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() 完成。
  • 你始终知道自己在操作哪个对象。

Pasted image 20261009231151

等价的 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')