Matplotlib:双轴柱状图与折线图如何合并显示单个图例?
解决Matplotlib双轴图表合并图例的问题
你遇到的问题确实是因为bar()和plot()返回的对象类型不同导致的——ax.bar()返回的是BarContainer(本质是元组),而ax.plot()返回的是包含Line2D对象的列表,直接用+拼接这两种类型自然会触发类型错误。下面是完整的解决方案,帮你把两个轴的元素合并到同一个图例框里:
修正后的完整代码
import pandas as pd import matplotlib.pyplot as plt df = pd.DataFrame() df["bar"] = [40,35,50,45] df["line"] = [.5,.3,.2,.6] fig, ax = plt.subplots(2) # 绘制左轴柱状图,获取BarContainer对象 bar_container = ax[0].bar(df.index, df["bar"], label='my bar chart (left axis)', color='royalblue', width=0.55) # 创建右轴 ax_right = ax[0].twinx() # 绘制右轴折线图,获取Line2D对象列表 line_objects = ax_right.plot(df.index, df['line'], label='my line (right axis)', color='tomato', marker='.', ls='dashed') # 关键步骤:统一对象类型并合并图例元素 # 把BarContainer转成列表,再和折线图的对象列表合并 combined_handles = list(bar_container) + line_objects # 提取所有元素的标签 combined_labels = [handle.get_label() for handle in combined_handles] # 在主轴上创建合并后的图例(替换原来的两个独立图例) ax[0].legend(handles=combined_handles, labels=combined_labels, loc='upper left', fancybox=True, title='My title') plt.show()
为什么这个方法有效?
- 类型统一:
list(bar_container)把元组类型的BarContainer转换成了列表,这样就能和line_objects(列表类型)顺利拼接,得到一个包含柱状图patch和折线图Line2D对象的统一列表。 - 合并图例:通过
ax[0].legend()传入合并后的handles和labels,就能在同一个图例框里显示两个轴的元素,不需要再手动调整第二个图例的位置来避免重叠。
额外小技巧
如果你的柱状图只有一组(像示例里这样),也可以直接取BarContainer的第一个元素来简化代码:
combined_handles = [bar_container[0]] + line_objects
这个写法和list(bar_container)效果一样,不过list(bar_container)更通用,适合多组柱状图的场景。
内容的提问来源于stack exchange,提问作者Pythonista anonymous
相关产品推荐
相关产品推荐

