放置颜色条#

颜色条指示图像数据的定量范围. 将其放置在图中并非易事,因为需要为它们留出空间.

自动放置颜色条#

最简单的情况是将颜色条附加到每个 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)
colorbar placement

第一列在两行中具有相同类型的数据,因此可能希望只有一个颜色条. 我们通过将 Axes 列表传递给 Figure.colorbar 的 ax kwarg 来做到这一点.

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=axs[:, col], shrink=0.6)
colorbar placement

被盗空间可能导致同一 subplot 布局中的 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)
colorbar placement

这通常是不希望的,并且可以通过各种方式解决,例如,向其他 Axes 添加颜色条然后将其删除. 但是,最直接的方法是使用 constrained layout :

fig, axs = plt.subplots(2, 1, figsize=(4, 5), sharex=True, layout='constrained')
axs[0].plot(np.sum(X, axis=0))
pcm = axs[1].pcolormesh(X)
fig.colorbar(pcm, ax=axs[1], shrink=0.6)
colorbar placement

使用此范例,可以实现相对复杂的颜色条布局. 请注意,此示例在 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')
colorbar placement

调整颜色条和父 Axes 之间的间距#

可以使用 pad 关键字参数调整颜色条与父 Axes 的距离. 这是以父 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'")
layout='constrained'

请注意,如果不使用 constrained layout,则 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")
No layout manager

手动放置颜色条#

有时, colorbar 提供的自动放置无法提供所需的效果. 我们可以手动创建一个 Axes,并通过将 Axes 传递给 cax 关键字参数来告诉 colorbar 使用该 Axes.

使用 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')
colorbar placement

如果您希望您的 Axes 位于图表上的某个数据位置,则 Axes.inset_axes 也可以使用 transform 关键字参数在数据坐标中指定其位置:

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')
colorbar placement

附加到固定纵横比 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)
colorbar placement

我们使用 Axes.inset_axes 在"axes coordinates"中定位 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)
colorbar placement

脚本的总运行时间:(0 分钟 6.648 秒)

Gallery generated by Sphinx-Gallery