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

如何让Matplotlib图例跨越多张子图的绘图区域?

解决共享图例宽度匹配子图绘图区域的问题

核心问题原因

你遇到的图例不遵循指定bbox的问题,本质是没有明确指定图例的坐标系统,且未启用图例宽度填充模式。constrained布局下,子图位置是动态调整的,默认的axes坐标系统会让你的bbox计算值被错误转换,导致图例位置偏移、宽度失控。

解决方案步骤

  1. 切换到figure坐标系统:通过bbox_transform=fig.transFigure让图例的bbox基于整个画布计算,不受子图坐标干扰。
  2. 获取子图的最终figure坐标:constrained布局会动态调整子图位置,需在绘制后获取子图的实际位置范围。
  3. 启用宽度填充模式:设置mode='expand'强制图例宽度匹配你指定的bbox宽度。

修改后的示例代码

import matplotlib.pyplot as plt

# 创建带constrained布局的子图
fig, axes = plt.subplots(2, 2, constrained_layout=True)

# 绘制子图内容并收集线条对象
lines = []
for ax in axes.flat:
    line, = ax.plot([1, 2, 3], label=f'Line {ax._axes_number}')
    lines.append(line)

# 先绘制一次,确保子图位置是constrained布局调整后的最终位置
plt.draw()

# 获取所有子图的figure坐标范围
subplots_pos = [ax.get_position() for ax in axes.flat]
x_left = min(p.x0 for p in subplots_pos)
x_right = max(p.x1 for p in subplots_pos)
y_bottom = min(p.y0 for p in subplots_pos) - 0.1  # 向下留出图例空间

# 创建匹配子图宽度的共享图例
fig.legend(
    lines, [l.get_label() for l in lines],
    bbox_to_anchor=(x_left, y_bottom, x_right - x_left, 0.08),  # (左, 下, 宽, 高)
    loc='upper left',
    bbox_transform=fig.transFigure,  # 关键:使用figure坐标
    mode='expand',  # 强制图例宽度填充指定的bbox宽度
    borderaxespad=0  # 消除图例内部与边框的间距,让宽度完全匹配
)

plt.show()

关键细节说明

  • plt.draw():constrained布局会在第一次绘制时调整子图位置,提前调用它能确保你拿到的是子图的最终坐标,避免计算偏差。
  • borderaxespad=0:消除图例内部元素与边框的默认间距,让图例宽度完全贴合你指定的bbox范围。
  • 若需要将图例放在子图上方,只需调整y_bottom为max(p.y1 for p in subplots_pos) + 0.05即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 13:24:58