Matplotlib legend无标签句柄报错及双轴图例优雅设置方法
报错根因
- 第一次调用
ax1.legend(loc=0)时,ax1轴下仅绘制了绿色的y1曲线,你未给这条线设置label参数,该轴下没有任何带有效标签的图例句柄,直接触发"No handles with labels found to put in legend"报错。 - 你试图通过在
ax2上绘制值为np.nan的透明线来补绿色曲线标签的写法逻辑绕路,且后续又调用plt.legend(),默认仅会捕获当前活跃轴(即后创建的ax2)的图例句柄,既会遗漏ax1的真实线条,还会出现两次生成图例导致的重叠、覆盖问题。
双y轴场景的规范图例实现
不需要用绘制空占位线的取巧方案,直接合并两个坐标轴的图例句柄,生成统一图例即可,逻辑清晰且易维护:
- 绘图时给所有线条显式设置
label参数,不要遗漏 - 分别从两个坐标轴提取已生成的线条对象(句柄)
- 合并两个轴的句柄和对应标签,单次调用
legend()生成整合后的图例,避免多次调用引发展示问题
修正后的可运行代码:
x = datasetB1780v1["Settlement_Period"] y1 = datasetB1780v1["Imbalance_Quantity_(MWh)"] y2 = datasetB1780v1["Insufficient_balance_Price_Amount"] y3 = datasetB1780v1["Excess_balance_Price_Amount"] + 30 fig, ax1 = plt.subplots() # 直接给ax1上的线条设置label,无需额外绘制nan占位线 line_green = ax1.plot(x, y1, 'green', label='Imbalance Quantity (MWh)') ax2 = ax1.twinx() line_black = ax2.plot(x, y2, 'black', label='Insufficient balance Price Amount') line_yellow = ax2.plot(x, y3, 'yellow', label='Excess balance Price Amount (+30 offset)') # 合并两个轴的所有图例句柄与标签 all_handles = line_green + line_black + line_yellow all_labels = [handle.get_label() for handle in all_handles] # 单次调用生成统一图例,可自由选择放在ax1/ax2上,loc参数按需调整 ax1.legend(all_handles, all_labels, loc=0) ax1.set_xlabel('Settlement_Period') ax1.set_ylabel('Imbalance_Quantity', color='green') ax2.set_ylabel('Insufficient/Excess_balance_Price_Amount', color='b') plt.xticks(np.arange(0, len(x)+1, 1)) plt.show()
该方案优势:
- 无冗余的占位绘图代码,逻辑直观易维护,后续增删线条、调整样式时不需要额外修改图例部分的适配代码
- 仅生成一个整合图例,不会出现图例重叠、部分线条标签遗漏的问题
- 可灵活调整图例位置,如需避免遮挡曲线,可加
bbox_to_anchor=(1.15, 1)参数将图例放在绘图区域外侧
内容的提问来源于stack exchange,提问作者Jaime Romero Mijancos
相关产品推荐
相关产品推荐

