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

Matplotlib多面板图:自定义子图与Colorbar布局问题求助

解决Matplotlib 9张子图面板布局问题

需求回顾

  • 每列顶部两个子图(如(0,0)与(1,0)、(0,1)与(1,1)、(0,2)与(1,2))共享X轴,无垂直间距,右侧共用一个覆盖两者高度的垂直色条
  • 每列底部子图((2,0)、(2,1)、(2,2))与上方子图保留合理垂直间距,每个底部子图下方有独立水平色条
  • 所有子图图像尺寸和宽高比一致

现有代码的问题

  1. 仅用3x3的GridSpec未给顶部子图的共用色条预留空间,导致每个顶部子图单独生成色条,不符合“共用”需求
  2. 顶部两行子图间存在默认垂直间距,未实现“无间距”要求
  3. 色条通过make_axes_locatable添加,容易破坏整体布局的一致性,导致子图尺寸偏移

改进方案与代码

通过嵌套GridSpec和主GridSpec结合,精准控制每部分布局:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib import cm
from numpy.random import randn

# 创建主GridSpec:3行,6列(3组子图+色条),宽度比例控制子图和色条宽度,行间距设置合理间距
gs_main = gridspec.GridSpec(3, 6, 
                            width_ratios=[1, 0.05, 1, 0.05, 1, 0.05],  # 子图:色条宽度比例
                            hspace=0.2,  # 底部子图与上方的间距
                            height_ratios=[1, 1, 1])  # 保证所有子图高度一致

# 强制顶部两行子图无垂直间距
gs_main[0:2].update(hspace=0)

data = np.clip(randn(10, 10), -1, 1)
fig = plt.figure(figsize=(12, 8))  # 可根据需求调整整体尺寸

for j in range(3):  # 遍历每一列
    # --- 顶部两个子图 ---
    ax_top1 = plt.subplot(gs_main[0, 2*j])
    im_top1 = ax_top1.imshow(data, cmap=cm.viridis, vmin=-1, vmax=1)
    ax_top1.text(5,5,"0"+str(j),fontweight="bold")
    ax_top1.set(yticklabels=[], xticklabels=[])
    ax_top1.tick_params(axis='both', which='both', length=0)  # 隐藏刻度线

    ax_top2 = plt.subplot(gs_main[1, 2*j], sharex=ax_top1)
    im_top2 = ax_top2.imshow(data, cmap=cm.viridis, vmin=-1, vmax=1)
    ax_top2.text(5,5,"1"+str(j),fontweight="bold")
    ax_top2.set(yticklabels=[], xticklabels=[])
    ax_top2.tick_params(axis='both', which='both', length=0)
    plt.setp(ax_top1.get_xticklabels(), visible=False)  # 隐藏顶部子图的X轴标签

    # --- 顶部共用垂直色条 ---
    cax_v = plt.subplot(gs_main[0:2, 2*j+1])
    fig.colorbar(im_top1, cax=cax_v, ticks=[-1, 0, 1], orientation='vertical')

    # --- 底部子图与水平色条 ---
    # 嵌套GridSpec分配底部子图和色条的空间
    gs_bottom = gridspec.GridSpecFromSubplotSpec(2, 1, 
                                                 subplot_spec=gs_main[2, 2*j],
                                                 height_ratios=[10, 1],  # 子图:色条高度比例
                                                 hspace=0.1)
    ax_bottom = plt.subplot(gs_bottom[0])
    im_bottom = ax_bottom.imshow(data, cmap=cm.viridis, vmin=-1, vmax=1)
    ax_bottom.text(5,5,"2"+str(j),fontweight="bold")
    ax_bottom.set(yticklabels=[], xticklabels=[])
    ax_bottom.tick_params(axis='both', which='both', length=0)

    cax_h = plt.subplot(gs_bottom[1])
    fig.colorbar(im_bottom, cax=cax_h, ticks=[-1, 0, 1], orientation='horizontal')

plt.tight_layout()
plt.show()

代码说明

  1. 主GridSpec设计:用6列实现3组“子图+色条”的布局,通过width_ratios控制色条宽度,height_ratios保证所有子图高度一致;顶部两行的hspace设为0,实现无垂直间距
  2. 顶部子图共享X轴:通过sharex参数绑定顶部两个子图的X轴,隐藏顶部子图的X轴标签,避免重复
  3. 共用垂直色条:将色条放在覆盖顶部两行的GridSpec区域,直接绑定其中一个子图的图像对象(因数据范围一致,共用色条有效)
  4. 底部子图与色条:用嵌套GridSpec为每个底部子图单独分配色条空间,保证子图和色条的布局一致性,同时与上方子图保留合理间距

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 18:35:33