📈 Matplotlib

从零开始的数据分析之旅

📖 Matplotlib:Python可视化的根基

Matplotlib是Python最基础也最重要的可视化库,几乎所有高级绘图库(Seaborn、Plotly等)都构建在它之上。掌握Matplotlib,你就能绘制任何想要的图表,并拥有完全的控制力。

Matplotlib架构: Figure (画布) ├ Axes (坐标系) ← 绑定到Figure │ ├ Axis (坐标轴: X/Y) │ │ ├ Tick (刻度) │ │ └ Label (标签) │ ├ Line2D (线条) │ ├ Bar (柱状) │ ├ Scatter (散点) │ ├ Text (文本) │ └ Legend (图例) └ 可以有多个Axes (子图) 两种接口: ──────── pyplot (plt.xxx): 快速绘图,MATLAB风格 OO (fig, ax): 精细控制,推荐方式

1. 折线图

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2*np.pi, 100)

fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x, np.sin(x), 'b-', label='sin(x)', linewidth=2)
ax.plot(x, np.cos(x), 'r--', label='cos(x)', linewidth=2)
ax.set_title('折线图: sin & cos')
ax.legend()
ax.grid(True, alpha=0.3)
plt.savefig('line_chart.png', dpi=150, bbox_inches='tight')

📊 四大基础图表

图表适用场景核心函数数据类型
折线图趋势/变化ax.plot()时间序列/连续
柱状图比较/排名ax.bar()分类/离散
散点图关系/分布ax.scatter()两个连续变量
饼图占比/构成ax.pie()比例数据

柱状图

categories = ['A', 'B', 'C', 'D']
values = [23, 45, 56, 78]
colors = ['#3b82f6', '#60a5fa', '#93c5fd', '#bfdbfe']

ax.bar(categories, values, color=colors, edgecolor='white')
for i, v in enumerate(values):
    ax.text(i, v+1, str(v), ha='center')  # 数据标签

散点图

np.random.seed(42)
sx = np.random.randn(50)
sy = np.random.randn(50)

ax.scatter(sx, sy, c=np.abs(sx), cmap='coolwarm', s=100, 
           alpha=0.7, edgecolors='white')

饼图

labels = ['Python', 'R', 'SQL', 'Java', '其他']
sizes = [35, 20, 25, 12, 8]
explode = (0.05, 0, 0, 0, 0)

ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%')

🎨 子图布局与样式

子图布局

# 2×2子图
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes[0,0].plot(...)   # 左上
axes[0,1].bar(...)    # 右上
axes[1,0].scatter(...)  # 左下
axes[1,1].pie(...)    # 右下

# 不规则布局
fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(212)  # 占满底部

深色主题

plt.style.use('dark_background')
# 或手动设置
plt.rcParams.update({
    'figure.facecolor': '#0f0f1a',
    'axes.facecolor': '#1a1a2e',
    'text.color': '#e0e0e0',
    'axes.labelcolor': '#e0e0e0',
})
保存图表时用bbox_inches='tight'避免标签被截断,用dpi=150+保证清晰度。

📐 2024-2025 可视化前沿

🎨 图表美化技巧

# 自定义调色板
blue_palette = ['#0f172a','#1e40af','#3b82f6','#60a5fa','#93c5fd']

# 注释与标注
ax.annotate('最大值', 
    xy=(np.pi/2, 1),
    xytext=(2, 0.8),
    arrowprops=dict(arrowstyle='->', color='#60a5fa', lw=2),
    fontsize=12, color='#60a5fa')

# 文本框
ax.text(0.5, -0.5, 'y = sin(x)', fontsize=14,
    bbox=dict(boxstyle='round', facecolor='#1a1a2e',
              edgecolor='#3b82f6', alpha=0.8),
    color='#e0e0e0')

📊 高级图表类型

# 堆叠柱状图
ax.bar(categories, product_a, label='A', color='#3b82f6')
ax.bar(categories, product_b, bottom=product_a, label='B', color='#60a5fa')

# 水平柱状图
ax.barh(categories, values, color='#3b82f6')

# 面积图
ax.fill_between(x, np.sin(x), alpha=0.3, color='#3b82f6')

# 热力图(Matplotlib版)
data = np.random.randn(10, 10)
im = ax.imshow(data, cmap='coolwarm', aspect='auto')
plt.colorbar(im, ax=ax)

💻 完整实战代码

#!/usr/bin/env python3
# Matplotlib — 完整实战

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np

# ============ 折线图 ============
x = np.linspace(0, 2*np.pi, 100)
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

axes[0,0].plot(x, np.sin(x), 'b-', label='sin(x)', linewidth=2)
axes[0,0].plot(x, np.cos(x), 'r--', label='cos(x)', linewidth=2)
axes[0,0].set_title('折线图: sin & cos')
axes[0,0].legend()
axes[0,0].grid(True, alpha=0.3)

# ============ 柱状图 ============
categories = ['A', 'B', 'C', 'D']
values = [23, 45, 56, 78]
colors = ['#3b82f6', '#60a5fa', '#93c5fd', '#bfdbfe']
axes[0,1].bar(categories, values, color=colors, edgecolor='white')
axes[0,1].set_title('柱状图')
for i, v in enumerate(values):
    axes[0,1].text(i, v+1, str(v), ha='center')

# ============ 散点图 ============
np.random.seed(42)
sx = np.random.randn(50)
sy = np.random.randn(50)
axes[1,0].scatter(sx, sy, c=np.abs(sx), cmap='coolwarm', s=100, alpha=0.7, edgecolors='white')
axes[1,0].set_title('散点图')
axes[1,0].grid(True, alpha=0.3)

# ============ 饼图 ============
labels = ['Python', 'R', 'SQL', 'Java', '其他']
sizes = [35, 20, 25, 12, 8]
explode = (0.05, 0, 0, 0, 0)
axes[1,1].pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
              colors=['#3b82f6','#60a5fa','#93c5fd','#bfdbfe','#dbeafe'])
axes[1,1].set_title('饼图')

plt.tight_layout()
plt.savefig('charts.png', dpi=100, bbox_inches='tight')
print("图表已保存")

# ============ 深色主题 ============
plt.style.use('dark_background')
fig2, ax = plt.subplots(figsize=(8, 4))
ax.plot(np.cumsum(np.random.randn(100)), color='#3b82f6', linewidth=1.5)
ax.set_title('随机游走')
ax.grid(True, alpha=0.2)
plt.savefig('dark.png', dpi=100, bbox_inches='tight')
print("深色主题图表已保存")

print("\n✅ Python验证通过 — 折线/柱状/散点/饼图")
🏆 成就解锁:折线/柱状/散点/饼图
Python验证通过 — 四种图表全部成功生成并保存为PNG。2×2子图布局正确,深色主题应用成功。折线图sin/cos曲线、柱状图带数据标签、散点图带颜色映射、饼图带百分比标签。
思考题:
① Figure和Axes的关系是什么?
② plt.xxx接口和fig,ax接口的区别和推荐?
③ 如何保存高分辨率图表?
④ 深色主题下如何确保文字可读?

📝 课后练习

  1. 用Matplotlib绘制5种不同类型的图表
  2. 实现双Y轴图表(左轴温度,右轴降水量)
  3. 创建一个包含注释和箭头的图表
  4. 实现动画图表(FuncAnimation)
  5. 自定义一套适合论文的图表样式
📚 参考资料:
• Matplotlib官方文档: matplotlib.org/stable
• Matplotlib Gallery: matplotlib.org/stable/gallery
• Python Data Science Handbook (Jake VanderPlas)
• SciencePlots: github.com/garrettj404/SciencePlots

🗺️ 图表类型选择指南

图表类型选择决策树: 你想展示什么? ├ 趋势/变化 → 折线图 plot() │ ├ 单变量 → 简单折线 │ └ 多变量 → 多条线 + 图例 ├ 比较/排名 → 柱状图 bar() │ ├ 分类比较 → 竖柱状图 │ └ 水平排名 → 横柱状图 barh() ├ 关系/分布 → 散点图 scatter() │ ├ 两变量关系 → 散点图 │ └ 加趋势线 → regplot() ├ 占比/构成 → 饼图 pie() │ ├ 简单占比 → 饼图 │ └ 层级构成 → 嵌套饼图 ├ 分布形状 → 直方图 hist() │ ├ 单变量分布 → hist+KDE │ └ 组间对比 → 箱线图/小提琴图 └ 时间序列 → 折线图+滚动平均 ├ 趋势 → rolling().mean() └ 季节 → 周期性分析

Matplotlib保存参数指南

用途格式DPI尺寸
网页显示PNG100-15010×6英寸
论文投稿PDF/EPS300+期刊要求
PPT演示PNG150-20012×8英寸
打印海报PNG/TIFF300+实际尺寸
交互网页SVG矢量自适应

🔑 本课关键要点

Matplotlib核心5条:
① 推荐用OO接口(fig, ax)而非pyplot(plt)接口
② 四大基础图:折线(趋势)、柱状(比较)、散点(关系)、饼图(占比)
③ 保存时用bbox_inches='tight'避免截断,dpi=150+保证清晰
④ 深色主题:plt.style.use('dark_background')
⑤ 子图用plt.subplots(行, 列)创建
# Matplotlib速查
fig, ax = plt.subplots(figsize=(10, 6))

# 四大图表
ax.plot(x, y)              # 折线
ax.bar(categories, values) # 柱状
ax.scatter(x, y)           # 散点
ax.pie(sizes, labels=labs) # 饼图

# 美化
ax.set_title('标题')
ax.set_xlabel('X轴')
ax.legend()
ax.grid(True, alpha=0.3)

# 保存
plt.savefig('fig.png', dpi=150, bbox_inches='tight')
Matplotlib性能优化:①大数据量用alpha避免过度绘制 ②十万级数据点用rasterized=True ③百万级考虑Datashader ④保存PDF时矢量图可能很大,用dpi控制。
Matplotlib常见错误:①中文字体缺失导致方块——安装中文字体或用plt.rcParams['font.sans-serif']=['SimHei'] ②保存时标签被截断——加bbox_inches='tight' ③子图标题重叠——plt.tight_layout() ④颜色循环不够——自定义color列表。