设置Matplotlib颜色条大小以匹配图形

Ell*_*iot 134 python image matplotlib

我不能让像这样的imshow图上的colorbar与图形的高度相同,而不是事后使用Photoshop.我如何达到匹配的高度?颜色条尺寸不匹配的示例

sky*_*ker 193

无论显示器的大小如何,这种组合(以及接近这些组合的值)似乎"神奇地"对我来说是保持颜色条缩放到绘图.

plt.colorbar(im,fraction=0.046, pad=0.04)
Run Code Online (Sandbox Code Playgroud)

它也不需要共享轴,这可以使图形超出正方形.

  • 为最简单但有效的答案提供支持! (23认同)
  • 这是实现它的唯一通用方式.使用axex_grid1的解决方案不适用于GeoAxes等投影轴. (6认同)
  • 这可能在某些情况下有效,但一般情况下则不然.尝试,例如,绘制原始问题中的内容,其宽度是高度的两倍. (3认同)
  • 回应@Matthias评论。您可以使用以下技巧纠正图像过宽的情况:`im_ratio = data.shape [0] /data.shape [1]`plt.colorbar(im,fraction = 0.046 * im_ratio,pad = 0.04)`其中“数据”是您的图像。 (3认同)

bog*_*ron 167

您可以使用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)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 这略微改变了图形的大小.我在2x2网格中有4个,但只希望右边的两个有条形(比例适用于行).然而,这使它们的大小不同.我试着没有使用colorbar调用(使用分频器调用),但当然这会留下一个空白框和侧面的数字.如何让它们具有一致的尺寸而不在所有尺寸上放置条形图? (10认同)
  • 我不在子图中工作,所以这不适用。 (2认同)
  • @user2820579,您可以在添加颜色条之前调用“plt.title”。这至少会使标题集中在主角身上...... (2认同)

Mat*_*ias 26

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

要获得正确的高度给定的纵横比,您必须深入了解神秘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)
Run Code Online (Sandbox Code Playgroud)

请注意,这指定了颜色条的宽度与图的高度(与图的宽度形成对比,如前所述).

现在可以将颜色条和绘图之间的间距指定为颜色条宽度的一小部分,这是IMHO比图形宽度的一小部分更有意义的数字.

带有colorbar的图像图

更新:

在这个主题上创建了一个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)
Run Code Online (Sandbox Code Playgroud)

它可以像这样使用:

im = plt.imshow(np.arange(200).reshape((20, 10)))
add_colorbar(im)
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常有用的小功能!需要警告的是,当您想要添加多个颜色条时,它不起作用,因为它们出现在彼此的顶部。 (2认同)

Pet*_*rke 14

另一种选择是

shrink=0.7, aspect=20*0.7
Run Code Online (Sandbox Code Playgroud)

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


Ste*_*nes 9

colorbar使用fraction和/或shrink参数创建try时.

从文件:

分数0.15; 用于colorbar的原始轴的一部分

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


Bog*_*dan 8

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

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

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

打电话给

cax = divider.append_axes("right", size=width, pad=pad)
Run Code Online (Sandbox Code Playgroud)

会失败的: KeyException: map_projection

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

ax.colorbar(im, fraction=0.046, pad=0.04)
Run Code Online (Sandbox Code Playgroud)

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


Fei*_*Yao 6

我感谢上面的所有答案。然而,像一些答案和评论中指出,该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)
Run Code Online (Sandbox Code Playgroud)

结果

在此处输入图片说明

后来,我发现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)
Run Code Online (Sandbox Code Playgroud)

结果

在此处输入图片说明

同样,您也可以通过指定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)
Run Code Online (Sandbox Code Playgroud)

结果

在此处输入图片说明

  • IMO 这是正确的答案,因为它完全绕过了 Matplotlib 的不可配置轴调整逻辑。真正令人沮丧的是,“使颜色条与‘ax=’轴高度相同”不是一个功能,并且需要像这样下降到低级别的图形/轴摆弄。 (2认同)