在数据可视化中,有时需要添加额外的文字说明来强调关键数据点、解释趋势或提供上下文。
Matplotlib 提供了 text() 和 annotate() 两个强大的函数来在图表中添加文本注释和标注箭头。
本章将详细介绍如何灵活运用它们,让你的图表更加信息丰富且易于理解。
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()
可以使用 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 字典可以设置背景框样式。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 是文本位置。arrowprops 字典可以设置箭头的各种属性:
| 参数 | 说明 | 示例 |
|---|---|---|
arrowstyle | 箭头风格 | '->', '-[', '<-', 'fancy' |
color | 箭头颜色 | 'red' |
lw 或 linewidth | 线宽 | 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 控制箭头连接线的弯曲方式。可以使用 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)。在字符串中使用 $...$ 可以渲染 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 避免转义。可以在字符串中使用换行符 \n,并设置 verticalalignment 和 horizontalalignment:
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()
循环遍历数据点,为每个点添加标注:
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()
面向对象方式,在每个子图上使用 ax.text 或 ax.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()
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()
使用 savefig() 保存包含注释的图表:
plt.savefig('annotated_plot.png', dpi=300, bbox_inches='tight')
文本注释和标注是让图表更具故事性的重要工具。掌握这些技巧后,你可以创建更富有洞察力的可视化作品。下一章我们将学习如何自定义样式和颜色,让图表更加美观。