注意
跳转到末尾以下载完整的示例代码。
放置颜色条#
颜色条表示图像数据的定量范围。在图中放置它们并非易事,因为需要为它们腾出空间。
颜色条的自动放置#
最简单的情况是为每个 Axes 附加一个颜色条。请注意,在此示例中,颜色条会占用父 Axes 的一些空间。
import matplotlib.pyplot as plt
import numpy as np
# Fixing random state for reproducibility
np.random.seed(19680801)
fig, axs = plt.subplots(2, 2)
cmaps = ['RdBu_r', 'viridis']
for col in range(2):
for row in range(2):
ax = axs[row, col]
pcm = ax.pcolormesh(np.random.random((20, 20)) * (col + 1),
cmap=cmaps[col])
fig.colorbar(pcm, ax=ax)

第一列的两行数据类型相同,因此可能只希望有一个颜色条。我们通过将带有 ax 关键字参数的 Axes 列表传递给 Figure.colorbar
来实现这一点。

占用的空间可能导致同一子图布局中的 Axes 大小不同,如果每个图的 x 轴旨在进行比较(如下所示),这通常是不希望的
fig, axs = plt.subplots(2, 1, figsize=(4, 5), sharex=True)
X = np.random.randn(20, 20)
axs[0].plot(np.sum(X, axis=0))
pcm = axs[1].pcolormesh(X)
fig.colorbar(pcm, ax=axs[1], shrink=0.6)

这通常是不希望的,可以通过多种方式解决,例如,向其他 Axes 添加颜色条,然后将其删除。但是,最直接的方法是使用 约束布局

使用这种范式可以实现相对复杂的颜色条布局。请注意,此示例在使用 layout='constrained'
时效果会好得多
fig, axs = plt.subplots(3, 3, layout='constrained')
for ax in axs.flat:
pcm = ax.pcolormesh(np.random.random((20, 20)))
fig.colorbar(pcm, ax=axs[0, :2], shrink=0.6, location='bottom')
fig.colorbar(pcm, ax=[axs[0, 2]], location='bottom')
fig.colorbar(pcm, ax=axs[1:, :], location='right', shrink=0.6)
fig.colorbar(pcm, ax=[axs[2, 1]], location='left')

调整颜色条与父 Axes 之间的间距#
颜色条与父 Axes 的距离可以通过 pad 关键字参数进行调整。此距离的单位是父 Axes 宽度的分数,垂直 Axes 的默认值为 0.05(水平 Axes 的默认值为 0.15)。
fig, axs = plt.subplots(3, 1, layout='constrained', figsize=(5, 5))
for ax, pad in zip(axs, [0.025, 0.05, 0.1]):
pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis')
fig.colorbar(pcm, ax=ax, pad=pad, label=f'pad: {pad}')
fig.suptitle("layout='constrained'")

请注意,如果您不使用约束布局,pad 命令会使父 Axes 缩小
fig, axs = plt.subplots(3, 1, figsize=(5, 5))
for ax, pad in zip(axs, [0.025, 0.05, 0.1]):
pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis')
fig.colorbar(pcm, ax=ax, pad=pad, label=f'pad: {pad}')
fig.suptitle("No layout manager")

颜色条的手动放置#
有时,colorbar
提供的自动放置效果不尽如人意。我们可以手动创建一个 Axes,并通过将该 Axes 传递给 cax 关键字参数来告诉 colorbar
使用它。
使用 inset_axes
#
我们可以手动创建任何类型的 Axes 供颜色条使用,但 Axes.inset_axes
很有用,因为它是一个父 Axes 的子级,并且可以相对于父级进行定位。这里我们在父 Axes 底部附近添加了一个居中的颜色条。
fig, ax = plt.subplots(layout='constrained', figsize=(4, 4))
pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis')
ax.set_ylim([-4, 20])
cax = ax.inset_axes([0.3, 0.07, 0.4, 0.04])
fig.colorbar(pcm, cax=cax, orientation='horizontal')

Axes.inset_axes
还可以使用 transform 关键字参数指定其在数据坐标中的位置,如果您希望您的 Axes 位于图上的特定数据位置
fig, ax = plt.subplots(layout='constrained', figsize=(4, 4))
pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis')
ax.set_ylim([-4, 20])
cax = ax.inset_axes([7.5, -1.7, 5, 1.2], transform=ax.transData)
fig.colorbar(pcm, cax=cax, orientation='horizontal')

附加到固定长宽比 Axes 的颜色条#
为具有固定长宽比的 Axes 放置颜色条带来了特殊的挑战,因为父 Axes 的大小会根据数据视图而变化。
fig, axs = plt.subplots(2, 2, layout='constrained')
cmaps = ['RdBu_r', 'viridis']
for col in range(2):
for row in range(2):
ax = axs[row, col]
pcm = ax.pcolormesh(np.random.random((20, 20)) * (col + 1),
cmap=cmaps[col])
if col == 0:
ax.set_aspect(2)
else:
ax.set_aspect(1/2)
if row == 1:
fig.colorbar(pcm, ax=ax, shrink=0.6)

我们使用 Axes.inset_axes
来解决这个问题,以在“轴坐标”(参见 变换教程)中定位 Axes。请注意,如果您放大父 Axes,从而改变其形状,颜色条的位置也会随之改变。
fig, axs = plt.subplots(2, 2, layout='constrained')
cmaps = ['RdBu_r', 'viridis']
for col in range(2):
for row in range(2):
ax = axs[row, col]
pcm = ax.pcolormesh(np.random.random((20, 20)) * (col + 1),
cmap=cmaps[col])
if col == 0:
ax.set_aspect(2)
else:
ax.set_aspect(1/2)
if row == 1:
cax = ax.inset_axes([1.04, 0.2, 0.05, 0.6])
fig.colorbar(pcm, cax=cax)

脚本总运行时间: (0 分 10.177 秒)