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

Matplotlib子图添加外部色条后如何保持相同帧宽度?

解决Matplotlib子图因色条导致宽度不一致的问题

我需要生成包含大量曲线的两个子图,因此定义了一个生成色条(colorbar)的函数,以避免使用过长且难以阅读的图例。创建色条的函数如下:

import matplotlib as mpl, matplotlib.pyplot as plt

def colorbar(cmap, vmin, vmax, label, ax=None, **cbar_opts):
    norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax, clip=False)
    cbar = plt.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),
                        label=label, ax=ax, **cbar_opts)
    return cbar

由于两个子图的色条取值范围相同,我仅在第二个子图右侧添加一个色条,代码如下:

import pandas as pd, numpy as np

df1 = pd.DataFrame({i: np.linspace(i*i, 10, 10) for i in range(50)})
df2 = pd.DataFrame({i: np.linspace(2*i*i, 10, 10) for i in range(50)})

fig, axs = plt.subplots(1,2, figsize=(5,3))
df1.plot(ax=axs[0], legend=False, cmap='turbo')
df2.plot(ax=axs[1], legend=False, cmap='turbo')

colorbar(ax = axs[1], cmap='turbo', vmin=0, vmax=49, label='My title')

axs[1].set_title('I want this frame \n as large as \n the first one')

plt.tight_layout()

问题:现在两个子图的宽度不同,因为色条被计入第二个子图的宽度测量中,如何让两个子图的帧宽度保持一致?


解决方案1:使用make_axes_locatable分割轴区域

通过mpl_toolkits.axes_grid1.make_axes_locatable工具,为色条单独创建一个轴,避免占用原子图的空间,确保两个子图宽度一致。

修改后的完整代码:

import pandas as pd, numpy as np
import matplotlib as mpl, matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

def colorbar(cmap, vmin, vmax, label, ax=None, **cbar_opts):
    norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax, clip=False)
    cbar = plt.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),
                        label=label, ax=ax, **cbar_opts)
    return cbar

df1 = pd.DataFrame({i: np.linspace(i*i, 10, 10) for i in range(50)})
df2 = pd.DataFrame({i: np.linspace(2*i*i, 10, 10) for i in range(50)})

fig, axs = plt.subplots(1,2, figsize=(5,3))
df1.plot(ax=axs[0], legend=False, cmap='turbo')
df2.plot(ax=axs[1], legend=False, cmap='turbo')

# 分割第二个子图的轴,为色条创建独立空间
divider = make_axes_locatable(axs[1])
cax = divider.append_axes("right", size="5%", pad=0.1)
colorbar(cmap='turbo', vmin=0, vmax=49, label='My title', cax=cax)

axs[1].set_title('I want this frame \n as large as \n the first one')

plt.tight_layout()
plt.show()

解决方案2:使用GridSpec规划布局

通过GridSpec设置布局的列宽度比例,让两个子图占用相同宽度的列,色条单独占用一列窄空间,从根源上保证子图宽度一致。

修改后的完整代码:

import pandas as pd, numpy as np
import matplotlib as mpl, matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

def colorbar(cmap, vmin, vmax, label, ax=None, **cbar_opts):
    norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax, clip=False)
    cbar = plt.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap=cmap),
                        label=label, ax=ax, **cbar_opts)
    return cbar

df1 = pd.DataFrame({i: np.linspace(i*i, 10, 10) for i in range(50)})
df2 = pd.DataFrame({i: np.linspace(2*i*i, 10, 10) for i in range(50)})

# 定义1行3列的布局,前两列宽度相同,第三列用于色条
fig = plt.figure(figsize=(5,3))
gs = GridSpec(1, 3, width_ratios=[1, 1, 0.05])

ax1 = fig.add_subplot(gs[0])
ax2 = fig.add_subplot(gs[1])
cax = fig.add_subplot(gs[2])

df1.plot(ax=ax1, legend=False, cmap='turbo')
df2.plot(ax=ax2, legend=False, cmap='turbo')

colorbar(cmap='turbo', vmin=0, vmax=49, label='My title', cax=cax)

ax2.set_title('I want this frame \n as large as \n the first one')

plt.tight_layout()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 10:40:53