Matplotlib折线图与柱状图get_label行为差异及统一取标签方案
Matplotlib折线图与柱状图get_label()行为差异及统一方案
问题背景
在使用Matplotlib绘制折线图时,可以通过以下方式获取所有标签并构建图例:
p1 = ax1.plot(x, 'P1', data=df) p2 = ax1.plot(x, 'P2', data=df) p3 = ax1.plot(x, 'P3', data=df) p4 = ax1.plot(x, 'P4', data=df) p = p1+p2+p3+p4 labs = [l.get_label() for l in p] ax1.legend(p, labs, loc=0, frameon=False)
但相同逻辑应用在柱状图时失效,示例代码如下:
b1 = ax1.bar(x-2*w, 'B1', data=df, width=w, label="TP") b2 = ax1.bar(x-w, 'B2', data=df, width=w, label="FN") b3 = ax1.bar(x, 'B3', data=df, width=w, label="FP") b4 = ax2.bar(x+w, 'B4', data=df, width=w, label="AP") b5 = ax2.bar(x+2*w, 'B5', data=df, width=w, label="AR")
调用b1.get_label()返回的是类似Series的字符串:
'0 87 Name: TP, dtype: object'
行为差异原因
折线图plot()的标签逻辑
plot()方法结合data参数使用时,若传入列名作为y轴数据,会自动将该列名设为线条的默认标签;如果显式指定label参数,会直接覆盖默认值。plot()返回的是Line2D对象列表,每个对象的get_label()会返回正确的标签字符串(列名或指定的label)。
柱状图bar()的标签逻辑
bar()方法结合data参数使用时,若传入列名作为height参数,默认会将该列对应的Series对象的字符串表示作为标签,即使显式指定label参数也会被忽略(这是Matplotlib处理bar()方法data参数的特殊逻辑,早期版本表现更明显)。这就是调用get_label()返回异常字符串的原因。
统一获取标签的方案
方法1:显式提取label属性值
直接从绘图对象的属性中提取指定的label值,兼容折线图与柱状图的逻辑:
# 收集所有绘图对象(注意plot返回的是列表,需取第一个元素) plots = [p1[0], p2[0], p3[0], p4[0], b1, b2, b3, b4, b5] # 统一获取标签:Line2D用get_label(),柱状图用properties()取label labs = [obj.get_label() if isinstance(obj, plt.Line2D) else obj.properties()['label'] for obj in plots] # 对应轴创建图例 ax1.legend([p1[0], p2[0], p3[0], p4[0], b1, b2, b3], labs[:7], loc=0, frameon=False) ax2.legend([b4, b5], labs[7:], loc=0, frameon=False)
方法2:修改bar()调用方式
放弃data参数的列名写法,直接传入数据值并显式指定label,让get_label()返回正确值:
# 直接传入DataFrame列的数值,而非列名字符串 b1 = ax1.bar(x-2*w, df['B1'], width=w, label="TP") b2 = ax1.bar(x-w, df['B2'], width=w, label="FN") b3 = ax1.bar(x, df['B3'], width=w, label="FP") b4 = ax2.bar(x+w, df['B4'], width=w, label="AP") b5 = ax2.bar(x+2*w, df['B5'], width=w, label="AR") # 现在可以和折线图完全一致的方式获取标签 bars = [b1, b2, b3, b4, b5] labs = [bar.get_label() for bar in bars] ax1.legend([b1, b2, b3], labs[:3], loc=0, frameon=False) ax2.legend([b4, b5], labs[3:], loc=0, frameon=False)
方法3:手动设置柱状图标签
如果坚持使用data参数的列名写法,可手动为每个柱状图对象设置标签,覆盖默认值:
b1 = ax1.bar(x-2*w, 'B1', data=df, width=w) b1.set_label("TP") b2 = ax1.bar(x-w, 'B2', data=df, width=w) b2.set_label("FN") b3 = ax1.bar(x, 'B3', data=df, width=w) b3.set_label("FP") b4 = ax2.bar(x+w, 'B4', data=df, width=w) b4.set_label("AP") b5 = ax2.bar(x+2*w, 'B5', data=df, width=w) b5.set_label("AR") # 正常使用get_label()获取标签 labs = [b.get_label() for b in [b1, b2, b3, b4, b5]]
内容的提问来源于stack exchange,提问作者Joysn
相关产品推荐
相关产品推荐

