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

如何将图例相对于GridSpec单元格对齐,为子图组配置独立图例

解决方案

核心思路是给图例专门预留网格位置,避免手动调整坐标,同时不挤压原有子图的显示空间:

  • 调整外层GridSpec结构,新增一列专门用于放置两个独立图例,通过宽度比例控制图例区域的宽度
  • 通过GridSpec自带的坐标获取方法拿到对应图例区域的边界,作为图例的对齐基准,无需手动计算锚点坐标
  • 图例对齐直接用loc参数即可自动适配预留区域,适配性强,画布尺寸修改后也不需要重新调整位置

修改后的可运行代码

#!/usr/bin/env python3
import pandas as pd, seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

GENOMES = ["spneumoniae", "ecoliK12", "scerevisiae", "celegans", "bmori", "hg38"]

fig = plt.figure(figsize = (7, 8))
# 修改外层网格:2行2列,新增右侧列放图例,宽度比例8.8:1.2,高度比例保持2:1
outer_grid = gridspec.GridSpec(2, 2, width_ratios=[0.88, 0.12], height_ratios = [2, 1])
# 原有子图网格都放在左侧第一列
inner_grid1 = gridspec.GridSpecFromSubplotSpec(4, 3, subplot_spec=outer_grid[0, 0])
inner_grid2 = gridspec.GridSpecFromSubplotSpec(2, 3, subplot_spec=outer_grid[1, 0])

# 先绘制所有子图
for index, genome in enumerate(GENOMES):
    data = pd.DataFrame({"x": [0, 1, 2, 3, 0, 1, 2, 3], "y": [1, 0, 3, 2, 1, 0, 3, 2], "hue": ["a", "a", "a", "a", "b", "b", "b", "b"]})

    # 第一组6幅子图
    ax1 = plt.Subplot(fig, inner_grid1[index])
    ax1 = sns.lineplot(data = data, x = "x", y = "y", hue = "hue", ax = ax1, legend=False)
    ax1.set_xlabel("")
    ax1.set_ylabel("")
    ax1.legend([], [], loc = "lower center", title = f"{genome}")
    fig.add_subplot(ax1)

    # 第二组6幅子图
    ax2 = plt.Subplot(fig, inner_grid1[index + 6])
    ax2 = sns.lineplot(data = data, x = "x", y = "y", hue = "hue", ax = ax2, legend=False)
    ax2.set_xlabel("")
    ax2.set_ylabel("")
    ax2.legend([], [], loc = "upper center", title = f"{genome}")
    fig.add_subplot(ax2)

    # 第三组6幅子图
    ax3 = plt.Subplot(fig, inner_grid2[index])
    ax3 = sns.lineplot(data = data, x = "x", y = "y", hue = "hue", ax = ax3, legend=False)
    ax3.set_xlabel("")
    ax3.set_ylabel("")
    ax3.legend([], [], loc = "upper center", title = f"{genome}")
    fig.add_subplot(ax3)

# 单独生成两个图例,自动对齐到右侧预留区域
# 获取inner_grid1对应的右侧图例区域坐标
legend1_box = outer_grid[0,1].get_position(fig)
handles1, labels1 = ax1.get_legend_handles_labels()
fig.legend(handles1, labels1, loc="center left", bbox_to_anchor=legend1_box, bbox_transform=fig.transFigure)

# 获取inner_grid2对应的右侧图例区域坐标
legend2_box = outer_grid[1,1].get_position(fig)
handles2, labels2 = ax3.get_legend_handles_labels()
# 如需自定义标签直接替换labels2即可,比如labels2 = ["#unitigs", "avg. unitig len."]
fig.legend(handles2, labels2, loc="center left", bbox_to_anchor=legend2_box, bbox_transform=fig.transFigure)

plt.savefig("stackoverflow_test.pdf", bbox_inches="tight")

关键修改说明

  1. 预留图例位置:外层GridSpec新增右侧列,子图和图例区域完全分离,不会出现图例挤压子图缩放的问题
  2. 自动获取对齐基准:通过get_position方法直接拿到对应网格区域的坐标,无需手动计算bbox_to_anchor的数值,适配性极强
  3. 对齐逻辑简化:loc参数会自动基于预留的图例区域做对齐,比如center left就是对齐到预留区域的左侧中间位置,符合直觉不需要反复调试

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 09:24:01