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
相关产品推荐
相关产品推荐

