首页 > 解决方案 > Matplotlib 子图如何将颜色条与其他图例对齐,或如何将子图向左对齐

问题描述

如何向第二个和第三个子图添加颜色条比例,使其与我在第一个和第四个子图中的图例内联?或者,换一种说法:如何在不改变第二个和第三个子图的对齐/对齐方式的情况下添加颜色条比例?

在设置颜色条位置上有很好的示例(例如,在 stackoverflowmatplotlib 文档中),但我仍然无法解决这个问题。

下面是一个可重现的例子。真实数据更复杂,这是生成许多图形的循环的一部分,因此需要设置轴限制和子图纵横比的“额外”内容,并且会随着不同的数据集而变化。

使用 Python 3.8。

没有颜色条的可重现示例

## Specify axes limits, tick intervals, and aspect ratio
xl, yl, xytick, ar = [-40000,120000], [-30000,10000], 20000, 0.8

## Global plot layout stuff
fig = plt.figure(figsize=(10, 7.5), constrained_layout=True)
gs = fig.add_gridspec(4, 1)
ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[1, 0], sharex = ax1, sharey = ax1)
ax3 = fig.add_subplot(gs[2, 0], sharex = ax1)
ax4 = fig.add_subplot(gs[3, 0], sharex = ax1, sharey = ax3)
fig.execute_constrained_layout()
fig.suptitle('Suptitle')


## First Plot
ax1.plot([-30000, 500], [-2000, -21000], c='red', label='A')
ax1.plot([80000, 110000], [-9000, 800], c='blue', label='B')
ax1.set_title('ax1', style='italic');
ax1.set_xlabel('x');
ax1.set_ylabel('beta');
ax1.set_xlim(xl)
ax1.set_ylim(yl)
ax1.xaxis.set_major_locator(ticker.MultipleLocator(xytick))
ax1.yaxis.set_major_locator(ticker.MultipleLocator(xytick))
ax1.legend(handles=leg, bbox_to_anchor=(1.05, 1), loc='upper left')
ax1.set_aspect(aspect=ar)


## Dummy data for plots 2/3/4
x = [-15000, -2000, 0, 5000, 6000, 11000, 18000, 21000, 25000, 36000, 62000]
beta = [1000, 200, -800, 100, 1000, -2000, -5000, -5000, -15000, -21000, -1500]
y = [0.01, 0.2, 1.3, 0.35, 0.88, 2.2, 2.5, 1.25, 3.4, 4.1, 2.1]


## Second Plot
vals = ax2.scatter(x, beta, c=y, norm=mcolors.LogNorm(), cmap='rainbow')
ax2.set_title('ax2', style='italic');
ax2.set_xlabel('x');
ax2.set_ylabel('beta');
ax2.set_aspect(aspect=ar)

## Attempt to add colorbar
#cbar = fig.colorbar(vals, ax=ax2, format = '%1.2g', location='right', aspect=25)
#cbar.ax.set_ylabel('y')
#cbar.ax.yaxis.set_label_position('left')
#cbar_range = [min(y), max(y)]
#ticklabels = cbar.ax.get_ymajorticklabels()
#cbarticks = list(cbar.get_ticks())
#cbar.set_ticks(cbar_range + cbarticks)


## Third Plot
ax3.scatter(x, y, c=y, norm=mcolors.LogNorm(), cmap='rainbow')
ax3.set_title('ax3', style='italic');
ax3.set_xlabel('x');
ax3.set_ylabel('y');
ax3.yaxis.set_major_formatter(FormatStrFormatter('%1.2g'))


## Fourth Plot
ax4.scatter(x, y, c='black', label='Dots')
ax4.set_title('ax4', style='italic');
ax4.set_xlabel('x');
ax4.set_ylabel('y');
ax4.legend(bbox_to_anchor=(1.05, 1), loc='upper left')


## Clean-up, set aspect ratios
figW, figH = ax1.get_figure().get_size_inches()
_, _, w, h = ax1.get_position().bounds
disp_ratio = (figH * h) / (figW * w)
data_ratio = sub(*ax3.get_ylim()) / sub(*ax3.get_xlim())
ax3.set_aspect(aspect=disp_ratio / data_ratio )
ax4.set_aspect(aspect=disp_ratio / data_ratio)

## Clean-up, turn axis ticks back on after messing with cbar
#ax1.tick_params(axis='both', which='both', labelbottom='on')
#ax2.tick_params(axis='both', which='both', labelbottom='on')
#ax3.tick_params(axis='both', which='both', labelbottom='on')

在此处输入图像描述

尝试颜色条时的结果,注意第二个图的未对齐

在此处输入图像描述

标签: matplotliblegendsubplotcolorbar

解决方案


建议您简化代码并确保一切正常;例如,我不知道做什么sub

您的问题的部分解决方案可能是panchor=False,这有点晦涩难懂,但是......

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
## Specify axes limits, tick intervals, and aspect ratio
ar = 1.2

## Global plot layout stuff
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 4), constrained_layout=True, sharex=True, sharey=True)

## First Plot
ax1.plot([-20_000, 20_000], [-20_000, 20_000] )
ax1.set_aspect(aspect=ar)

## Dummy data for plots 2/3/4
x = [-15000, -2000, 0, 5000, 6000, 11000, 18000, 21000, 25000, 36000, 62000]
beta = [1000, 200, -800, 100, 1000, -2000, -5000, -5000, -15000, -21000, -1500]
y = [0.01, 0.2, 1.3, 0.35, 0.88, 2.2, 2.5, 1.25, 3.4, 4.1, 2.1]

## Second Plot
vals = ax2.scatter(x, beta, c=y, norm=mcolors.LogNorm(), cmap='rainbow')
ax2.set_aspect(aspect=ar)
cbar = fig.colorbar(vals, ax=ax2, format = '%1.2g', location='right',
                    aspect=25, panchor=False)

plt.show()

在此处输入图像描述

根据图形的大小,这可能会滑稽地将颜色条放在最右边。这里的问题是绘图的纵横比,这使得实际轴比图更窄。但是颜色条并不真正了解这一点,而是将自己放置在为轴分配的空间之外。

如果这令人不快,那么您还可以为颜色栏指定一个插入轴。

cbax = ax2.inset_axes([1.05, 0.2, 0.05, 0.6], transform=ax2.transAxes)
cbar = fig.colorbar(vals, cax=cbax, format = '%1.2g', orientation='vertical')

在此处输入图像描述


推荐阅读