01-面向对象绘图与高级定制

知识库
知识库文档
/tech-stacks/matplotlib/tutorial/01-面向对象绘图与高级定制.md

文档

Matplotlib 进阶 —— 面向对象绘图与出版级定制

本章目标

  • 深入理解 Figure / Axes / Artist 对象模型
  • 掌握出版级图形的定制技巧
  • 学会使用 Seaborn 快速美化

1. Matplotlib 对象模型

Figure(画布)
  ├── Axes(坐标轴/子图)         # 这就是你绘图的地方
  │   ├── Line2D(线条)
  │   ├── Scatter(散点)
  │   ├── Text(文字)
  │   ├── XAxis / YAxis
  │   └── Legend
  └── Axes
      └── ...

一个 Figure 可以有多个 Axes
每个 Axes 可以有多个 Artist(图形元素)

三种绘图方式

# ① pyplot 状态机(简单但不推荐大量使用)
plt.plot(x, y)
plt.title("Title")
plt.show()

# ② 面向对象(推荐)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title("Title")
plt.show()

# ③ Artist 底层(极少需要)
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
line = plt.Line2D(x, y)
ax.add_line(line)

2. 出版级图形定制

fig, ax = plt.subplots(figsize=(8, 5), dpi=150)

# 绘制
ax.plot(x, y, label="数据", color="#2196F3", linewidth=1.5, marker="o", markersize=4)

# 标题(可含 LaTeX)
ax.set_title(r"$\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}$", fontsize=14)

# 坐标轴标签
ax.set_xlabel("时间 (ms)", fontsize=12)
ax.set_ylabel("振幅 (mV)", fontsize=12)

# 刻度定制
ax.tick_params(labelsize=10, direction="in", top=True, right=True)
ax.minorticks_on()

# 图例
ax.legend(frameon=True, fancybox=True, shadow=True, loc="best")

# 注释
ax.annotate("峰值", xy=(np.pi/2, 1), xytext=(np.pi/2+1, 0.8),
            arrowprops=dict(arrowstyle="->", color="red"),
            fontsize=11, color="red")

# 网格
ax.grid(True, alpha=0.3, linestyle="--")

# 保存
fig.tight_layout()
fig.savefig("publication_figure.pdf", format="pdf", bbox_inches="tight",
            facecolor="white", edgecolor="none")

3. 高级图表类型

3.1 双 Y 轴

fig, ax1 = plt.subplots()

ax1.plot(x, y1, "b-", label="温度")
ax1.set_ylabel("温度 (°C)", color="b")

ax2 = ax1.twinx()
ax2.plot(x, y2, "r-", label="湿度")
ax2.set_ylabel("湿度 (%)", color="r")

fig.tight_layout()

3.2 热力图

fig, ax = plt.subplots()
im = ax.imshow(matrix, cmap="viridis", aspect="auto")
fig.colorbar(im, ax=ax, label="强度")
ax.set_xticks(range(len(labels)))
ax.set_xticklabels(labels, rotation=45)

3.3 3D 图形

fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")

X, Y = np.meshgrid(np.linspace(-5, 5, 50), np.linspace(-5, 5, 50))
Z = np.sin(np.sqrt(X**2 + Y**2))
ax.plot_surface(X, Y, Z, cmap="coolwarm", edgecolor="none")

4. Seaborn 快速美化

import seaborn as sns

# Seaborn 自动设置更美观的默认样式
sns.set_theme(style="whitegrid", palette="muted")

# 统计分析图(一行代码)
sns.boxplot(data=df, x="category", y="value")
sns.violinplot(data=df, x="group", y="score")
sns.pairplot(df, hue="species")
sns.heatmap(df.corr(), annot=True, cmap="coolwarm")

Matplotlib vs Seaborn

特性 Matplotlib Seaborn
灵活度 极高 中等(预定义布局)
默认美观 一般 优秀
DataFrame 集成 手动 原生支持
学习曲线 陡峭 平缓
适用场景 出版级定制 数据分析可视化

思考题

  1. plt.plot()ax.plot() 有什么区别?为什么推荐后者?
  2. 如何让 Matplotlib 图形在不同屏幕/设备上保持一致的尺寸?
  3. Seaborn 相比 Matplotlib 有什么本质区别(不是"更好看"这个层次)?
  4. 矢量格式(SVG/PDF)与位图格式(PNG)的选择标准是什么?

信息

路径
/tech-stacks/matplotlib/tutorial/01-面向对象绘图与高级定制.md
更新时间
2026/5/30