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

如何在Matplotlib约束布局中让子图网格的绘图与pcolor图同宽高比

问题

需要创建子图网格,要求所有子图尺寸与宽高比完全一致,同时混合使用pcolor图与普通绘图。其中pcolor图需固定宽高比保证像素方正,普通绘图也要适配该宽高比。尝试用constrained_layout=True约束子图尺寸,但子图要么过宽要么过高,布局严重依赖figure尺寸,不符合预期。

现象说明:

  • 当figsize=(8,11)时,普通绘图过宽;
  • 当figsize=(10,20)时,子图高度受色条影响而非左侧pcolor图高度;
  • 布局严重依赖figure尺寸,不符合预期。

预期效果:所有子图保持相同的宽度和高度,整齐排列;需要色条的子图搭配高度一致的色条。

原代码:

import matplotlib.pyplot as plt
import numpy as np
# Running this in jupyter
%matplotlib inline 

# Generating some random data to display
width, height = 265, 200 # dimensions of my "picture"
color_data = np.random.rand(height, width)
plot_data = np.random.rand(40)

# Creating the figure and subplots
fig, axes = plt.subplots(6, 2, figsize=(8,11), constrained_layout=True)
[[ax1, ax2], [ax3, ax4], [ax5, ax6], [ax7, ax8], [ax9, ax10], [ax11, ax12]] = axes

for ax in  [ax1, ax2, ax3, ax5, ax7, ax9, ax11]:
    art = ax.pcolor(color_data, vmin=0, vmax=1)
    # Every plot gets its own color bar, this is intended because I want
    # to mix different color plots of the same aspect ratio
    plt.colorbar(art, ax=ax, label='z',fraction=0.046, pad=0.04)
    ax.grid(False)
    ax.set_aspect(height/width)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.invert_yaxis()

for ax in [ax4, ax6, ax8, ax10, ax12]:
    ax.plot(np.arange(len(plot_data)), plot_data, color='blue', linewidth=2)
    ax.set_xlabel('index')
    ax.set_ylabel('value')

解决方案

核心思路是用matplotlib.gridspec.GridSpec手动规划子图布局,给带色条的子图额外预留色条空间,同时强制所有子图使用相同的宽高比,避免自适应布局的偏差。

修改后的代码:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.gridspec import GridSpec

%matplotlib inline 

# 数据参数
width, height = 265, 200
aspect_ratio = height / width
color_data = np.random.rand(height, width)
plot_data = np.random.rand(40)

# 创建GridSpec:6行,每行列分为主区域+色条区域(仅左侧子图需要色条)
# 列宽比例:主区域占95%,色条占5%,保证色条高度一致
gs = GridSpec(6, 3, width_ratios=[19, 19, 1], figure=plt.figure(figsize=(10, 18)))

# 遍历创建子图
for row in range(6):
    # 左侧子图(带pcolor和色条)
    ax_pcolor = plt.subplot(gs[row, 0])
    art = ax_pcolor.pcolor(color_data, vmin=0, vmax=1)
    ax_pcolor.grid(False)
    ax_pcolor.set_aspect(aspect_ratio)
    ax_pcolor.set_xlabel('x')
    ax_pcolor.set_ylabel('y')
    ax_pcolor.invert_yaxis()
    # 色条绑定到GridSpec预留的第三列位置
    cbar = plt.colorbar(art, cax=plt.subplot(gs[row, 2]), label='z')
    
    # 右侧子图(普通绘图)
    ax_plot = plt.subplot(gs[row, 1])
    ax_plot.plot(np.arange(len(plot_data)), plot_data, color='blue', linewidth=2)
    ax_plot.set_xlabel('index')
    ax_plot.set_ylabel('value')
    # 强制设置和pcolor子图匹配的宽高比(结合列宽比例换算)
    ax_plot.set_aspect(aspect_ratio * (gs.get_width_ratios()[0]/gs.get_width_ratios()[1]))

plt.tight_layout()

关键调整说明:

  • 用GridSpec将每一行拆分为三部分:左侧pcolor子图、右侧普通子图、色条区域,通过width_ratios固定宽度比例,确保色条高度与对应子图完全一致;
  • 给所有子图强制设置匹配的宽高比,普通子图需结合列宽比例换算,保证实际显示尺寸与pcolor子图统一;
  • 用tight_layout()替代constrained_layout,配合GridSpec的固定布局逻辑,避免自适应带来的尺寸偏差;
  • 色条直接绑定到GridSpec预留的位置,不再依赖自动调整,保证所有色条高度统一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:18:14