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

如何绘制不等列数、共享X轴的多子图?解决布局与图例难题

非规则网格子图布局与图例优化方案

一、非规则子图布局解决方案

针对每行列数不同、tight_layout报错的问题,推荐以下自动布局方案:

1. 正确启用constrained_layout

之前启用无效是因为时机错误,需在创建figure时直接指定参数,它支持非规则网格的自动间距调整:

fig = plt.figure(figsize=choose_size, clear=True, constrained_layout=True)

该参数会自动适配子图间距、标题位置,避免元素重叠。

2. 用subplot_mosaic定义非规则布局

如果子图结构固定,subplot_mosaic可直观定义每行列数,完美适配非规则排列:

# 示例:2行布局,第一行2个子图,第二行1个子图
fig, axs = plt.subplot_mosaic([
    ["row1_col1", "row1_col2"],
    ["row2_col1"]
], figsize=choose_size, constrained_layout=True)

# 对应子图绘图
axs["row1_col1"].plot(lvl_1[x_val], lvl_1[...])
axs["row1_col1"].set_title("xxx")
# 其他子图同理

3. 动态计算subplots_adjust参数

若坚持原有add_subplot逻辑,可根据行数、列数动态计算间距,替代手动调整:

n_rows = len(v1.keys())
max_cols = max(len(v2) for v2 in v1.values())  # 获取最大列数

fig.subplots_adjust(
    top=0.85,  # 给suptitle预留空间
    bottom=0.1,
    left=0.07,
    right=0.93,
    hspace=0.3 + 0.1*(n_rows>3),  # 行数多则增大行间距
    wspace=0.2 + 0.1*(max_cols>2)  # 列数多则增大列间距
)

4. 实现X轴共享

所有子图共享X轴,减少重复标签、节省空间:

first_ax = None  # 保存第一个子图作为共享基准

# 在创建子图的循环中添加:
ax = fig.add_subplot(...)
if first_ax is None:
    first_ax = ax
else:
    ax.sharex(first_ax)  # 绑定X轴共享

# 隐藏非底部子图的X轴标签
for ax in fig.axes:
    # 根据布局逻辑判断是否为最后一行
    if ax.get_subplotspec().rowspan.start != n_rows - 1:
        ax.set_xticklabels([])

二、图例优化方案

针对子图空间不足的问题,推荐以下清晰图例生成方式:

1. 全局统一图例

收集所有子图的图例项,在画布外侧单独放置:

# 收集唯一的图例手柄和标签
all_handles = []
all_labels = []
for ax in fig.axes:
    handles, labels = ax.get_legend_handles_labels()
    for h, l in zip(handles, labels):
        if l not in all_labels:
            all_handles.append(h)
            all_labels.append(l)

# 在画布右侧添加全局图例
fig.legend(
    all_handles, all_labels,
    loc="center right",
    bbox_to_anchor=(1.2, 0.5),  # 调整位置避免超出画布
    fontsize=10
)

2. 单独生成图例图片

若主图完全无空间,可单独导出图例文件:

# 创建仅含图例的画布
fig_legend = plt.figure(figsize=(2.5, 5))
fig_legend.legend(all_handles, all_labels, loc="center")
# 保存图例
legend_path = os.path.join(folder_results_path, f"{k1}_legend.png")
fig_legend.savefig(legend_path, bbox_inches="tight")
plt.close(fig_legend)

3. 精简图例标签

若标签过长,可截断或简化:

# 示例:将标签截断至15字符以内
short_label = _finally[:15] + "..." if len(_finally) >15 else _finally
ax.plot(lvl_1[x_val], lvl_1[_finally], label=short_label)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 07:20:21