You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为含字符串X轴的折线图添加数值标注?

解决折线图标注的ConversionError问题

错误原因很明确:你用df['Month']的字符串值(比如'JAN')作为plt.annotate的x坐标,但Matplotlib绘制折线图时,x轴底层实际使用的是DataFrame的索引值(0到11),Month列只是被用作x轴的刻度标签显示,并非真实的轴坐标值,所以直接传入字符串会触发类型转换错误。

下面给两种可行的解决方式:


方法一:使用DataFrame索引作为标注的x坐标

直接循环DataFrame的索引和对应MEAN值,用索引作为x轴坐标,同时保留原Month字符串作为刻度显示:

import matplotlib.pyplot as plt
import pandas as pd

# 你的DataFrame数据
data = {
    'Month': ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'],
    'MEAN': [1.0, 2.0, 5.0, 3.0, 4.0, 2.0, 1.0, 1.0, 0.0, 0.0, 2.0, 3.0]
}
df = pd.DataFrame(data)

fig = plt.figure('Graphic', figsize=(20,15), dpi=300)
ax1 = fig.add_axes([0.15, 0.20, 0.70, 0.60])
df.plot(kind='line', marker='o', style=['--'], linewidth=7, color='black', ms=15, ax=ax1)

# 修改循环:用索引i作为x坐标,y为MEAN值
for i, y in enumerate(df['MEAN']):
    label = "{:.2f}".format(y)
    # 用ax1.annotate替代plt.annotate,更精准绑定当前轴
    ax1.annotate(label, 
                 (i, y), 
                 textcoords="offset points", 
                 xytext=(0,10), 
                 ha='center')

# 确保x轴显示Month字符串(默认已经是,这里可以显式设置)
ax1.set_xticks(range(len(df)))
ax1.set_xticklabels(df['Month'])

plt.show()

关键改动:

  • 用enumerate(df['MEAN'])获取索引i(对应x轴的实际坐标)和y值
  • 用ax1.annotate替代plt.annotate,避免多轴场景下的混乱
  • 显式设置x轴刻度和标签,确保显示Month字符串

方法二:将Month转为有序分类类型

先把Month列转为有序分类,让Matplotlib能正确识别其作为x轴的映射关系:

import matplotlib.pyplot as plt
import pandas as pd

data = {
    'Month': ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'],
    'MEAN': [1.0, 2.0, 5.0, 3.0, 4.0, 2.0, 1.0, 1.0, 0.0, 0.0, 2.0, 3.0]
}
df = pd.DataFrame(data)

# 将Month转为有序分类,指定顺序确保绘图时的顺序正确
month_order = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
df['Month'] = pd.Categorical(df['Month'], categories=month_order, ordered=True)

fig = plt.figure('Graphic', figsize=(20,15), dpi=300)
ax1 = fig.add_axes([0.15, 0.20, 0.70, 0.60])
# 绘图时指定x为Month列
df.plot(x='Month', kind='line', marker='o', style=['--'], linewidth=7, color='black', ms=15, ax=ax1)

# 循环时用分类的编码值作为x坐标
for x, y in zip(df['Month'].cat.codes, df['MEAN']):
    label = "{:.2f}".format(y)
    ax1.annotate(label, 
                 (x, y), 
                 textcoords="offset points", 
                 xytext=(0,10), 
                 ha='center')

plt.show()

这种方式适合需要保留Month列作为分类数据的场景,通过cat.codes获取分类对应的数值坐标。


内容的提问来源于stack exchange,提问作者Javier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 11:57:09