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

使用plt.twinx()处理子图多图例时遇报错,求解决方案

双轴子图整合图例时出现AttributeError的解决方法

问题现象

使用plt.twinx()为子图设置双轴不同刻度后,尝试将子图所有标签整合到单个图例框时触发错误:

AttributeError: 'list' object has no attribute 'get_label'

其中柱状图子图的图例可正常整合,但折线+散点图的子图报错。

问题原因

  1. plt.plot()返回的是Line2D对象的列表(即使仅绘制一条线),而plt.scatter()返回PathCollection对象、plt.bar()返回BarContainer对象;
  2. 若直接将plt.plot()返回的列表传入plt.legend(handles=...),图例无法识别列表类型,需取出列表中的实际绘图对象(索引为0的元素)。

解决方案

折线+散点图子图(第一个子图)

  • 对plt.plot()返回的对象,通过索引[0]取出实际的Line2D对象;
  • 散点图返回的PathCollection对象可直接使用;
  • 收集所有绘图对象后,统一传入plt.legend(handles=...)。

柱状图子图(第二个子图)

plt.bar()返回的BarContainer对象本身支持图例识别,直接收集后传入即可(原有代码此部分逻辑正常)。

修正后的完整代码

import matplotlib
print('matplotlib: {}'.format(matplotlib.__version__))
# matplotlib: 3.2.2

# Generate data
import pandas as pd

df = pd.DataFrame(dict(
    Date   = [1,2,3],
    Male   = [10,20,30],
    Female = [20,30,10],
    Others = [700,500,200]
))
print(df)

#      Date  Male  Female     Others
# 0     1     10       20       700
# 1     2     20       30       500
# 2     3     30       10       200

# Create plots
import numpy as np
import matplotlib.pyplot as plt

Userx = 'foo'
fig, ax = plt.subplots(nrows=2, ncols=1 , figsize=(20,10))

# 第一个子图:折线+散点+双轴
plt.subplot(211)
# 直接取出plt.plot返回列表中的Line2D对象
linechart1, = plt.plot(df['Date'], df['Male'], color='orange', marker=".", markersize=5, label=f"Leg1 for {Userx}")
scatterchart2 = plt.scatter(df['Date'], df['Female'], color='#9b5777', marker='d', s=70, label=f"Leg2 for {Userx}")
plt.ylabel('Scale1', fontsize=15)

# 双轴
ax_twin1 = plt.twinx()
linechart3, = ax_twin1.plot(df['Date'], df['Others'], color='black', marker=".", markersize=5, label=f"Leg3 for {Userx}")
plt.ylabel('Scale2', fontsize=15)

# 收集所有绘图对象,整合图例
all_handles1 = [linechart1, scatterchart2, linechart3]
plt.legend(handles=all_handles1, loc='best', fontsize=15)
plt.xlabel('Timestamp [24hrs]', fontsize=15, color='darkred')
plt.ticklabel_format(style='plain')

# 第二个子图:柱状图+双轴
plt.subplot(212)
barchart1 = plt.bar(df['Date'], df['Male'], color='green', label=f"Leg1 for {Userx}", width=1, hatch='o')
barchart2 = plt.bar(df['Date'], df['Female'], color='blue', label=f"Leg2 for {Userx}", width=0.9, hatch='O')
plt.ylabel('Scale1', fontsize=15)
plt.ticklabel_format(style='plain')

# 双轴
ax_twin2 = plt.twinx()
barchart3 = ax_twin2.bar(df['Date'], df['Others'], color='orange', label=f"Leg3 for {Userx}", width=0.9, hatch='/', alpha=0.1)
plt.ylabel('Scale2', fontsize=15)
plt.ticklabel_format(style='plain')
plt.xlabel('Timestamp [24hrs]', fontsize=15, color='darkred')

# 整合图例
bar123 = [barchart1, barchart2, barchart3]
plt.legend(handles=bar123, loc='best', fontsize=15)

plt.show()

关键修正点

  1. 将linechart1 = plt.plot(...)改为linechart1, = plt.plot(...),直接取出列表中的Line2D对象;
  2. 双轴的linechart3同样使用linechart3, = ax_twin1.plot(...)的写法;
  3. 收集所有有效绘图对象后,统一调用一次plt.legend()整合所有标签。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 03:31:37