Matplotlib 绘图基础 —— 从 pyplot 到面向对象
目标
- 掌握 pyplot 快速绘图
- 理解 Figure/Axes 面向对象模型
- 掌握常见图表类型的绘制
- 中文显示与样式配置
完整代码
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
# ============================================================
# 0. 全局配置(推荐放在开头)
# ============================================================
plt.rcParams.update({
"figure.figsize": (10, 6),
"figure.dpi": 100,
"font.sans-serif": ["SimHei", "Microsoft YaHei"], # 中文字体
"axes.unicode_minus": False, # 负号正常显示
"axes.grid": True,
"grid.alpha": 0.3,
})
# ============================================================
# 1. 折线图(Line Plot)
# ============================================================
x = np.linspace(0, 2 * np.pi, 100)
fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(x, np.sin(x), label="sin(x)", color="#2196F3", linewidth=2)
ax.plot(x, np.cos(x), label="cos(x)", color="#FF5722", linewidth=2, linestyle="--")
ax.axhline(y=0, color="gray", linewidth=0.5) # 水平参考线
ax.set_title("三角函数", fontsize=14, fontweight="bold")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.legend(loc="upper right", frameon=True)
fig.tight_layout()
fig.savefig("line_plot.png", dpi=150, bbox_inches="tight")
plt.show()
# ============================================================
# 2. 散点图(Scatter Plot)
# ============================================================
np.random.seed(42)
n = 200
x = np.random.randn(n)
y = 2 * x + np.random.randn(n) * 0.5
colors = np.sqrt(x**2 + y**2)
sizes = np.abs(np.random.randn(n) * 50 + 100)
fig, ax = plt.subplots()
scatter = ax.scatter(x, y, c=colors, s=sizes, alpha=0.6, cmap="viridis")
ax.set_title("散点图(颜色表示距离,大小随机)")
fig.colorbar(scatter, ax=ax, label="距离原点")
plt.show()
# ============================================================
# 3. 柱状图(Bar Chart)
# ============================================================
categories = ["Python", "JavaScript", "Java", "C++", "Rust"]
values = [85, 70, 65, 55, 40]
errors = [3, 5, 4, 6, 2]
fig, ax = plt.subplots()
bars = ax.bar(categories, values, yerr=errors, capsize=5,
color=["#2196F3", "#FFC107", "#F44336", "#4CAF50", "#9C27B0"],
edgecolor="white", linewidth=1)
# 在柱上标注数值
for bar, val in zip(bars, values):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 2,
str(val), ha="center", fontsize=11)
ax.set_title("编程语言受欢迎度")
ax.set_ylabel("评分")
ax.set_ylim(0, 100)
plt.show()
# ============================================================
# 4. 直方图(Histogram)
# ============================================================
data = np.random.randn(10000)
fig, ax = plt.subplots()
ax.hist(data, bins=50, density=True, alpha=0.7, color="#4CAF50", edgecolor="white")
# 叠加理论正态分布曲线
x = np.linspace(-4, 4, 200)
ax.plot(x, 1/np.sqrt(2*np.pi) * np.exp(-x**2/2), "r-", linewidth=2, label="N(0,1)")
ax.set_title("标准正态分布直方图")
ax.legend()
plt.show()
# ============================================================
# 5. 饼图(Pie Chart)
# ============================================================
labels = ["工程部", "销售部", "市场部", "HR", "财务"]
sizes = [35, 25, 20, 12, 8]
explode = (0.05, 0, 0, 0, 0) # 突出第一块
fig, ax = plt.subplots()
wedges, texts, autotexts = ax.pie(
sizes, labels=labels, explode=explode, autopct="%1.1f%%",
startangle=90, colors=plt.cm.Set3.colors,
)
# 调整百分比文字样式
for t in autotexts:
t.set_fontsize(10)
t.set_fontweight("bold")
ax.set_title("部门人员分布")
plt.show()
# ============================================================
# 6. 多子图布局(GridSpec)
# ============================================================
from matplotlib.gridspec import GridSpec
fig = plt.figure(figsize=(12, 8))
gs = GridSpec(2, 3, figure=fig, hspace=0.3, wspace=0.3)
ax1 = fig.add_subplot(gs[0, 0])
ax1.plot(np.random.randn(50).cumsum())
ax1.set_title("随机游走")
ax2 = fig.add_subplot(gs[0, 1:])
ax2.scatter(np.random.randn(100), np.random.randn(100), alpha=0.5)
ax2.set_title("散点图")
ax3 = fig.add_subplot(gs[1, :2])
ax3.hist(np.random.randn(1000), bins=30, color="skyblue", edgecolor="white")
ax3.set_title("直方图")
ax4 = fig.add_subplot(gs[1, 2])
ax4.pie([30, 20, 50], labels=["A", "B", "C"], autopct="%d%%",
colors=["gold", "lightcoral", "lightskyblue"])
ax4.set_title("饼图")
fig.suptitle("GridSpec 多子图示例", fontsize=16, fontweight="bold")
plt.show()
# ============================================================
# 7. 样式与主题
# ============================================================
print("可用样式:", plt.style.available[:5])
# 使用内置样式
with plt.style.context("seaborn-v0_8-darkgrid"):
fig, ax = plt.subplots()
ax.plot(x, np.sin(x))
ax.set_title("seaborn-darkgrid 样式")
# 或全局设置
# plt.style.use("ggplot")
关键要点
| 概念 |
说明 |
plt.subplots() |
推荐:同时创建 Figure 和 Axes |
fig, ax = ... |
面向对象风格,比 pyplot 状态机更清晰 |
ax.set_*() |
Axes 级别的标题/标签/刻度设置 |
fig.savefig(dpi=) |
保存图片,支持 PNG/SVG/PDF |
plt.rcParams |
全局样式配置 |
GridSpec |
复杂的子图布局 |