222

我无法让像这样的 imshow 图表上的颜色条与图表的高度相同,事后没有使用 Photoshop。我如何获得匹配的高度?颜色条大小不匹配的示例

4

7 回答 7

275

这种组合(以及接近这些的值)似乎“神奇地”让我保持颜色条按比例缩放到绘图,无论显示尺寸如何。

plt.colorbar(im,fraction=0.046, pad=0.04)

它也不需要共享可以使绘图不方形的轴。

于 2014-11-03T18:18:07.063 回答
243

您可以使用 matplotlib AxisDivider轻松完成此操作。

链接页面中的示例也可以在不使用子图的情况下工作:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np
    
plt.figure()
ax = plt.gca()
im = ax.imshow(np.arange(100).reshape((10,10)))
    
# create an axes on the right side of ax. The width of cax will be 5%
# of ax and the padding between cax and ax will be fixed at 0.05 inch.
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
   
plt.colorbar(im, cax=cax)

在此处输入图像描述

于 2013-08-12T20:15:55.407 回答
50

我很感激上面的所有答案。但是,就像一些答案和评论指出的那样,该axes_grid1模块无法解决 GeoAxes,而调整fractionpadshrink和其他类似参数不一定能给出非常精确的顺序,这真的让我很困扰。我相信给colorbar它自己的axes可能是解决所有提到的问题的更好的解决方案。

代码

import matplotlib.pyplot as plt
import numpy as np

fig=plt.figure()
ax = plt.axes()
im = ax.imshow(np.arange(100).reshape((10,10)))

# Create an axes for colorbar. The position of the axes is calculated based on the position of ax.
# You can change 0.01 to adjust the distance between the main image and the colorbar.
# You can change 0.02 to adjust the width of the colorbar.
# This practice is universal for both subplots and GeoAxes.

cax = fig.add_axes([ax.get_position().x1+0.01,ax.get_position().y0,0.02,ax.get_position().height])
plt.colorbar(im, cax=cax) # Similar to fig.colorbar(im, cax = cax)

结果

在此处输入图像描述

后来,我发现matplotlib.pyplot.colorbar官方文档也提供了ax选项,它们是现有的轴,将为颜色条提供空间。因此,它对多个子图很有用,见下文。

代码

fig, ax = plt.subplots(2,1,figsize=(12,8)) # Caution, figsize will also influence positions.
im1 = ax[0].imshow(np.arange(100).reshape((10,10)), vmin = -100, vmax =100)
im2 = ax[1].imshow(np.arange(-100,0).reshape((10,10)), vmin = -100, vmax =100)
fig.colorbar(im1, ax=ax)

结果

在此处输入图像描述

同样,您也可以通过指定 cax 来实现类似的效果,从我的角度来看,这是一种更准确的方式。

代码

fig, ax = plt.subplots(2,1,figsize=(12,8))
im1 = ax[0].imshow(np.arange(100).reshape((10,10)), vmin = -100, vmax =100)
im2 = ax[1].imshow(np.arange(-100,0).reshape((10,10)), vmin = -100, vmax =100)
cax = fig.add_axes([ax[1].get_position().x1-0.25,ax[1].get_position().y0,0.02,ax[0].get_position().y1-ax[1].get_position().y0])
fig.colorbar(im1, cax=cax)

结果

在此处输入图像描述

于 2019-07-05T10:01:10.043 回答
43

@bogatron 已经给出了matplotlib docs建议的答案,它产生了正确的高度,但它引入了一个不同的问题。现在颜色条的宽度(以及颜色条和绘图之间的空间)随着绘图的宽度而变化。换句话说,颜色条的纵横比不再固定。

要获得正确的高度给定的纵横比,您必须更深入地挖掘神秘的axes_grid1模块。

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable, axes_size
import numpy as np

aspect = 20
pad_fraction = 0.5

ax = plt.gca()
im = ax.imshow(np.arange(200).reshape((20, 10)))
divider = make_axes_locatable(ax)
width = axes_size.AxesY(ax, aspect=1./aspect)
pad = axes_size.Fraction(pad_fraction, width)
cax = divider.append_axes("right", size=width, pad=pad)
plt.colorbar(im, cax=cax)

请注意,这指定了颜色条的宽度和绘图的高度(与之前的图形宽度相反)。

现在可以将颜色条和绘图之间的间距指定为颜色条宽度的一部分,恕我直言,这是一个比图形宽度的一部分更有意义的数字。

带颜色条的图像绘图

更新:

我创建了一个关于该主题的 IPython 笔记本,将上面的代码打包成一个易于重用的函数:

import matplotlib.pyplot as plt
from mpl_toolkits import axes_grid1

def add_colorbar(im, aspect=20, pad_fraction=0.5, **kwargs):
    """Add a vertical color bar to an image plot."""
    divider = axes_grid1.make_axes_locatable(im.axes)
    width = axes_grid1.axes_size.AxesY(im.axes, aspect=1./aspect)
    pad = axes_grid1.axes_size.Fraction(pad_fraction, width)
    current_ax = plt.gca()
    cax = divider.append_axes("right", size=width, pad=pad)
    plt.sca(current_ax)
    return im.axes.figure.colorbar(im, cax=cax, **kwargs)

它可以这样使用:

im = plt.imshow(np.arange(200).reshape((20, 10)))
add_colorbar(im)
于 2015-11-03T17:30:45.303 回答
14

以上所有解决方案都很好,但我最喜欢@Steve's 和@bejota's,因为它们不涉及花哨的调用并且是通用的。

通用是指适用于任何类型的轴,包括GeoAxes. 例如,如果您有用于映射的投影轴:

projection = cartopy.crs.UTM(zone='17N')
ax = plt.axes(projection=projection)
im = ax.imshow(np.arange(200).reshape((20, 10)))

打电话给

cax = divider.append_axes("right", size=width, pad=pad)

将失败:KeyException: map_projection

因此,使用所有类型的轴处理颜色条大小的唯一通用方法是:

ax.colorbar(im, fraction=0.046, pad=0.04)

使用从 0.035 到 0.046 的分数以获得最佳尺寸。但是,fraction 和 paddig 的值需要调整以最适合您的绘图,并且会根据颜色条的方向是垂直位置还是水平位置而有所不同。

于 2016-10-09T20:39:24.243 回答
13

当您colorbar使用分数和/或收缩参数创建尝试时。

从文件:

分数 0.15; 用于颜色条的原始轴的分数

收缩 1.0;缩小颜色条的分数

于 2013-08-12T20:23:40.693 回答
4

另一种选择是

shrink=0.7, aspect=20*0.7

shrink缩放高度和宽度,但aspect参数恢复原始宽度。默认纵横比为 20。根据0.7经验确定。

于 2021-06-03T04:03:57.393 回答