图表修饰:文本注释与标注

在数据可视化中,有时需要添加额外的文字说明来强调关键数据点、解释趋势或提供上下文。 Matplotlib 提供了 text()annotate() 两个强大的函数来在图表中添加文本注释和标注箭头。 本章将详细介绍如何灵活运用它们,让你的图表更加信息丰富且易于理解。

📝 1. 使用 plt.text() 添加文本

plt.text(x, y, s, ...) 在指定的坐标 (x,y) 处添加文本字符串 s:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
y = np.sin(x)

plt.plot(x, y)
plt.text(2, 0.5, '正弦曲线', fontsize=12, color='blue')
plt.title('添加文本')
plt.show()
✔️ 文本默认以数据坐标为基准放置。

🎨 2. 定制文本样式

可以使用 fontsize, color, fontweight, bbox 等参数:

plt.plot(x, y)
plt.text(5, 0, '中心点', fontsize=14, color='white',
         bbox=dict(facecolor='red', alpha=0.5, boxstyle='round'))
plt.title('带边框的文本')
plt.show()
✔️ bbox 字典可以设置背景框样式。

➡️ 3. 使用 annotate 添加箭头标注

annotate() 可以在文本和指定点之间绘制箭头,非常适合突出某个数据点:

plt.plot(x, y)
# 标注峰值点
max_idx = np.argmax(y)
max_x, max_y = x[max_idx], y[max_idx]
plt.annotate('峰值', xy=(max_x, max_y), xytext=(max_x+1, max_y-0.5),
             arrowprops=dict(arrowstyle='->', color='red'))
plt.title('箭头标注')
plt.show()
✔️ xy 是箭头指向的点,xytext 是文本位置。

🔧 4. 定制箭头样式

arrowprops 字典可以设置箭头的各种属性:

参数说明示例
arrowstyle箭头风格'->', '-[', '<-', 'fancy'
color箭头颜色'red'
lwlinewidth线宽2
shrink箭头两端收缩比例0.1
headwidth箭头头部宽度10
frac箭头头部占箭头总长的比例0.3
plt.plot(x, y)
plt.annotate('重要点', xy=(np.pi, 0), xytext=(5, 0.8),
             arrowprops=dict(arrowstyle='fancy', color='green',
                             connectionstyle='arc3,rad=0.3',
                             linewidth=2))
plt.title('复杂箭头样式')
plt.show()
✔️ connectionstyle 控制箭头连接线的弯曲方式。

📍 5. 使用相对坐标放置文本

可以使用 transform=ax.transAxes 将坐标轴相对坐标(0~1)转换为数据坐标,便于在固定位置添加标注:

fig, ax = plt.subplots()
ax.plot(x, y)
ax.text(0.5, 0.95, '左上角说明', transform=ax.transAxes,
        fontsize=12, verticalalignment='top',
        bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
plt.title('相对坐标文本')
plt.show()
✔️ transform=ax.transAxes 使用轴坐标,左上角为 (0,1)。

∑ 6. 使用数学表达式

在字符串中使用 $...$ 可以渲染 LaTeX 风格的数学公式(需要启用 usetex 或直接支持):

plt.plot(x, y)
plt.text(5, 0.5, r'$\sin(x)$', fontsize=16)
plt.text(6, -0.3, r'$\sum_{n=1}^{\infty} \frac{1}{n^2} = \frac{\pi^2}{6}$', fontsize=12)
plt.title('数学表达式')
plt.show()
✔️ 记得字符串前加 r 避免转义。

📄 7. 多行文本

可以在字符串中使用换行符 \n,并设置 verticalalignmenthorizontalalignment

plt.plot(x, y)
plt.text(5, 0, '第一行\n第二行\n第三行', fontsize=12,
         ha='center', va='center',
         bbox=dict(facecolor='lightblue', alpha=0.8))
plt.title('多行文本')
plt.show()

🔖 8. 标注多个点

循环遍历数据点,为每个点添加标注:

x_points = [1, 3, 5, 7, 9]
y_points = [2, 4, 3, 5, 7]
plt.scatter(x_points, y_points)

for i, (xi, yi) in enumerate(zip(x_points, y_points)):
    plt.annotate(f'P{i+1}({xi},{yi})', xy=(xi, yi), xytext=(xi+0.3, yi+0.3),
                 arrowprops=dict(arrowstyle='->', color='gray'))

plt.title('多点标注')
plt.show()

🔲 9. 在子图中添加注释

面向对象方式,在每个子图上使用 ax.textax.annotate

fig, axes = plt.subplots(1, 2, figsize=(10, 4))

x = np.linspace(0, 2*np.pi, 100)
axes[0].plot(x, np.sin(x))
axes[0].annotate('峰值', xy=(np.pi/2, 1), xytext=(2, 0.8),
                 arrowprops=dict(arrowstyle='->'))
axes[0].set_title('sin(x)')

axes[1].plot(x, np.cos(x))
axes[1].text(0.5, 0.5, 'cos(x)', transform=axes[1].transAxes,
             fontsize=14, ha='center')
axes[1].set_title('cos(x)')

plt.tight_layout()
plt.show()

🏆 10. 综合示例

import matplotlib.pyplot as plt
import numpy as np

# 模拟股票价格数据
days = np.arange(1, 31)
price = 100 + np.cumsum(np.random.randn(30))  # 随机游走

plt.figure(figsize=(12, 6))
plt.plot(days, price, 'b-o', label='股价')

# 标注最高点
max_idx = np.argmax(price)
max_day, max_price = days[max_idx], price[max_idx]
plt.annotate(f'最高价: {max_price:.1f}', xy=(max_day, max_price),
             xytext=(max_day+2, max_price-5),
             arrowprops=dict(arrowstyle='fancy', color='red', lw=2),
             fontsize=11, bbox=dict(boxstyle='round', facecolor='lightyellow'))

# 标注最低点
min_idx = np.argmin(price)
min_day, min_price = days[min_idx], price[min_idx]
plt.annotate(f'最低价: {min_price:.1f}', xy=(min_day, min_price),
             xytext=(min_day-3, min_price+5),
             arrowprops=dict(arrowstyle='->', color='green', connectionstyle='arc3,rad=0.2'),
             fontsize=11)

# 添加说明文本
plt.text(0.02, 0.98, '股票走势图\n数据基于随机生成',
         transform=plt.gca().transAxes, fontsize=10,
         verticalalignment='top',
         bbox=dict(boxstyle='round', facecolor='lightblue', alpha=0.7))

plt.xlabel('交易日')
plt.ylabel('股价')
plt.title('股票价格走势及关键点标注')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
✔️ 综合运用了 annotate、text、箭头样式和相对坐标。

💾 11. 保存图表

使用 savefig() 保存包含注释的图表:

plt.savefig('annotated_plot.png', dpi=300, bbox_inches='tight')

文本注释和标注是让图表更具故事性的重要工具。掌握这些技巧后,你可以创建更富有洞察力的可视化作品。下一章我们将学习如何自定义样式和颜色,让图表更加美观。