Matplotlib多面板图:自定义子图与Colorbar布局问题求助
解决Matplotlib 9张子图面板布局问题
需求回顾
- 每列顶部两个子图(如(0,0)与(1,0)、(0,1)与(1,1)、(0,2)与(1,2))共享X轴,无垂直间距,右侧共用一个覆盖两者高度的垂直色条
- 每列底部子图((2,0)、(2,1)、(2,2))与上方子图保留合理垂直间距,每个底部子图下方有独立水平色条
- 所有子图图像尺寸和宽高比一致
现有代码的问题
- 仅用3x3的GridSpec未给顶部子图的共用色条预留空间,导致每个顶部子图单独生成色条,不符合“共用”需求
- 顶部两行子图间存在默认垂直间距,未实现“无间距”要求
- 色条通过
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()
代码说明
- 主GridSpec设计:用6列实现3组“子图+色条”的布局,通过
width_ratios控制色条宽度,height_ratios保证所有子图高度一致;顶部两行的hspace设为0,实现无垂直间距 - 顶部子图共享X轴:通过
sharex参数绑定顶部两个子图的X轴,隐藏顶部子图的X轴标签,避免重复 - 共用垂直色条:将色条放在覆盖顶部两行的GridSpec区域,直接绑定其中一个子图的图像对象(因数据范围一致,共用色条有效)
- 底部子图与色条:用嵌套GridSpec为每个底部子图单独分配色条空间,保证子图和色条的布局一致性,同时与上方子图保留合理间距
内容的提问来源于stack exchange,提问作者arnbobo
相关产品推荐
相关产品推荐

