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

Matplotlib柱状图图例重复、标签颜色匹配异常求解

问题描述

我正在制作欧冠冠军球队及其国内联赛最终排名的可视化图表,经测试按赛季循环逐根绘制柱形、按所属球队匹配柱体填充色与边框色的实现方式效果最佳,对应绘图代码如下:

fig,ax = plt.subplots()
fig.set_size_inches(16,8)
for s in P_df['Season']:
    x = s
    y = P_df.loc[P_df['Season'] == s, 'Position']
    y = y.to_list()[0]
    team = P_df.loc[P_df['Season'] == s, 'Team']
    team = team.to_list()[0]
    face = color_key[team]
    edge = color2nd_key[team]
    ax.bar(x,y,color=face,label=team,edgecolor =edge,linewidth =3)

直接调用默认图例时会出现重复的球队条目,因此我尝试传入去重后的球队列表生成图例,再循环遍历为图例标签匹配对应填充色与边框色,对应图例代码如下:

ax.legend(color_key,loc = 'upper right')
leg = ax.legend(P_df['Team'].unique(),bbox_to_anchor=(1.02, 1), loc='upper left', borderaxespad=0, facecolor = 'black',edgecolor ='white')
handles, labels = ax.get_legend_handles_labels()
la = set(labels)
la = list(la)
for label in la:
    for ha in ax.legend_.legendHandles:
        te = label
        e = color2nd_key[te]
        f = color_key[te]
        ha.set_edgecolor(e)
        ha.set_facecolor(f)

执行上述代码后出现异常:所有图例标签都被赋值为列表首个元素对应的颜色,异常效果见参考附图:
图例配色异常效果
现需要定位代码错误点,并给出更优的实现方案。

错误原因

代码存在三个核心问题:

  • 嵌套循环逻辑错误:外层每遍历到一个球队标签,内层就会遍历所有图例handle,把所有图例项的颜色统一改成当前标签对应的配色。循环全部执行完成后,所有图例项都会被最后一次遍历的标签配色覆盖,因此呈现全为同一种颜色的效果。
  • 重复调用ax.legend()属于无效冗余代码:第一次调用生成的右上角图例,会被第二次ax.legend()调用直接覆盖,没有实际作用。
  • 用set()对标签去重会打乱标签原有顺序,即便修正循环逻辑,也大概率出现标签与配色错位的问题。
最优实现方案

不需要事后遍历修改图例颜色,从绘图阶段就避免重复label生成,是最简单稳定的方案,代码如下:

fig,ax = plt.subplots()
fig.set_size_inches(16,8)
added_teams = set()

for s in P_df['Season']:
    # 用iloc取值比转列表更高效
    y = P_df.loc[P_df['Season'] == s, 'Position'].iloc[0]
    team = P_df.loc[P_df['Season'] == s, 'Team'].iloc[0]
    face = color_key[team]
    edge = color2nd_key[team]
    # 仅球队第一次出现时传入label,后续同球队柱形不设置label,从根源避免图例重复
    bar_label = team if team not in added_teams else ""
    added_teams.add(team)
    ax.bar(s, y, color=face, label=bar_label, edgecolor=edge, linewidth=3)

# 直接生成无重复图例,不需要二次修改颜色
ax.legend(bbox_to_anchor=(1.02, 1), loc='upper left', borderaxespad=0,
          facecolor='black', edgecolor='white')
plt.tight_layout()
plt.show()

如果需要自定义图例排序、完全掌控图例样式,可以手动构建图例元素,可维护性更强:

from matplotlib.patches import Patch

# 此处可自定义球队排序规则,默认按首次出现顺序排列
legend_teams = list(P_df['Team'].unique())
# 手动构建每个图例项的样式
legend_handles = [
    Patch(facecolor=color_key[t], edgecolor=color2nd_key[t], linewidth=3)
    for t in legend_teams
]
# 传入自定义handle和标签生成图例
ax.legend(handles=legend_handles, labels=legend_teams,
          bbox_to_anchor=(1.02, 1), loc='upper left', borderaxespad=0,
          facecolor='black', edgecolor='white')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 00:54:40