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

Matplotlib图例可视化异常求助:折线图图例显示问题排查

Seaborn折线图图例异常问题排查

我用Seaborn绘制折线图时遇到图例异常,具体问题如下:

  • 图例第2、4位置出现两个矩形
  • 仅显示黑色、蓝色、红色三种线条,黄色和绿色线条未正常显示
  • 已显示的三条线条颜色和代码中定义的不匹配

相关代码

var = 'eta_contraente'
target = 'target_accettazione'

DF = df_pred[[var,'target_accettazione','prediction_ret_1', 'prediction_ret_2',   'prediction_ret_3','prediction_ret_4_no_crawler']]

DF['pred_decili'] = pd.qcut(DF[var], list(np.linspace(0, 1, n)))

fig=plt.figure(figsize=(8, 5))
ax = fig.add_subplot(111)

mean_val = DF.groupby("pred_decili").mean().reset_index()
sns.lineplot(x=mean_val.index, y= target, 
             data=mean_val,  marker='s', color = 'black')

sns.lineplot(x=mean_val.index, y= "prediction_ret_1", 
             data=mean_val,  marker='s', color = 'blue')

sns.lineplot(x=mean_val.index, y= 'prediction_ret_2', 
             data=mean_val, marker='s', color = 'red')

sns.lineplot(x=mean_val.index, y= "prediction_ret_3", 
             data=mean_val,  marker='s', color = 'yellow')

sns.lineplot(x=mean_val.index, y= 'prediction_ret_4_no_crawler', 
             data=mean_val,  marker='s', color = 'green')

ax.set_xticks(mean_val.index)
ax.set_xticklabels(mean_val[var].round(), rotation = 60)

ax.legend([ 'black line', "blue line", "red line","yellow line","green line" ], loc='lower right', fontsize = 14);

问题截图

Seaborn折线图图例异常


问题原因

这是代码使用方式错误导致的,和matplotlib/pandas版本无关。核心问题在于手动调用ax.legend()的逻辑:

  1. Seaborn的lineplot默认会自动生成图例条目,手动传入自定义图例列表时,会和自动生成的条目冲突,出现重复矩形
  2. 手动指定图例时,未正确对应每个lineplot返回的线条对象,导致颜色不匹配、部分线条图例丢失

解决方案

方案1:手动收集线条对象,精准对应图例

每次调用sns.lineplot时保存返回的线条对象,再将对象与自定义标签一一对应:

var = 'eta_contraente'
target = 'target_accettazione'

DF = df_pred[[var,'target_accettazione','prediction_ret_1', 'prediction_ret_2',   'prediction_ret_3','prediction_ret_4_no_crawler']]
DF['pred_decili'] = pd.qcut(DF[var], list(np.linspace(0, 1, n)))

fig=plt.figure(figsize=(8, 5))
ax = fig.add_subplot(111)
mean_val = DF.groupby("pred_decili").mean().reset_index()

# 保存每个lineplot返回的线条对象
line1 = sns.lineplot(x=mean_val.index, y=target, data=mean_val, marker='s', color='black')
line2 = sns.lineplot(x=mean_val.index, y="prediction_ret_1", data=mean_val, marker='s', color='blue')
line3 = sns.lineplot(x=mean_val.index, y='prediction_ret_2', data=mean_val, marker='s', color='red')
line4 = sns.lineplot(x=mean_val.index, y="prediction_ret_3", data=mean_val, marker='s', color='yellow')
line5 = sns.lineplot(x=mean_val.index, y='prediction_ret_4_no_crawler', data=mean_val, marker='s', color='green')

ax.set_xticks(mean_val.index)
ax.set_xticklabels(mean_val[var].round(), rotation=60)

# 传入线条对象和对应标签
ax.legend([line1.lines[0], line2.lines[0], line3.lines[0], line4.lines[0], line5.lines[0]], 
          ['black line', "blue line", "red line","yellow line","green line"], 
          loc='lower right', fontsize=14)

方案2:用Seaborn的hue参数统一绘制(更简洁)

将数据整理成长格式,通过hue区分不同系列,自动生成正确图例:

var = 'eta_contraente'
target = 'target_accettazione'

DF = df_pred[[var,'target_accettazione','prediction_ret_1', 'prediction_ret_2',   'prediction_ret_3','prediction_ret_4_no_crawler']]
DF['pred_decili'] = pd.qcut(DF[var], list(np.linspace(0, 1, n)))
mean_val = DF.groupby("pred_decili").mean().reset_index()

# 转换为长格式数据
mean_val_long = mean_val.melt(id_vars='pred_decili', 
                             value_vars=[target, "prediction_ret_1", 'prediction_ret_2', "prediction_ret_3", 'prediction_ret_4_no_crawler'],
                             var_name='series', value_name='value')

fig=plt.figure(figsize=(8, 5))
ax = fig.add_subplot(111)

# 用hue区分系列,指定自定义颜色
sns.lineplot(x=mean_val_long.index, y='value', hue='series',
             data=mean_val_long, marker='s',
             palette={'target_accettazione':'black', 
                      'prediction_ret_1':'blue', 
                      'prediction_ret_2':'red', 
                      'prediction_ret_3':'yellow', 
                      'prediction_ret_4_no_crawler':'green'})

ax.set_xticks(mean_val.index)
ax.set_xticklabels(mean_val[var].round(), rotation=60)

# 自定义图例标签
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, ['black line', "blue line", "red line","yellow line","green line"], 
          loc='lower right', fontsize=14)

关键说明

  • 方案1通过手动绑定线条对象与图例,彻底解决冲突问题
  • 方案2是Seaborn推荐的用法,长格式数据+hue参数能更高效地管理多系列绘图,代码更简洁不易出错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 16:50:23