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 集成 |
手动 |
原生支持 |
| 学习曲线 |
陡峭 |
平缓 |
| 适用场景 |
出版级定制 |
数据分析可视化 |
思考题
plt.plot() 和 ax.plot() 有什么区别?为什么推荐后者?
- 如何让 Matplotlib 图形在不同屏幕/设备上保持一致的尺寸?
- Seaborn 相比 Matplotlib 有什么本质区别(不是"更好看"这个层次)?
- 矢量格式(SVG/PDF)与位图格式(PNG)的选择标准是什么?