Set Matplotlib colorbar size to match graph
我无法在像这样的imshow图上获得与该图相同的高度的色条,但事后没有使用Photoshop。 如何获得匹配的高度?
无论显示大小如何,这种组合(以及接近这些值的组合)似乎对我来说都是"神奇"的,可以使颜色条始终按图缩放。
1 | plt.colorbar(im,fraction=0.046, pad=0.04) |
它还不需要共享轴,该轴可以使绘图偏离正方形。
您可以使用matplotlib AxisDivider轻松完成此操作。
链接页面中的示例也可以在不使用子图的情况下运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
@bogatron已经给出了matplotlib文档所建议的答案,该答案产生正确的高度,但是它引入了另一个问题。
现在,颜色条的宽度(以及颜色条和图之间的空间)随图的宽度而变化。
换句话说,颜色条的纵横比不再固定。
为了获得正确的高度和给定的宽高比,您必须更深入地研究神秘的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
请注意,这指定了彩条的宽度。图的高度(与之前的宽度相反)。
现在可以将颜色条和图之间的间距指定为颜色条宽度的一部分,恕我直言,IMHO比图形宽度的一部分有意义得多。
更新:
我在该主题上创建了一个IPython笔记本,在其中将上面的代码打包到一个易于重用的函数中:
1 2 3 4 5 6 7 8 9 10 11 12 | 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) |
可以这样使用:
1 2 | im = plt.imshow(np.arange(200).reshape((20, 10))) add_colorbar(im) |
我感谢上述所有答案。但是,就像指出的一些答案和注释一样,
码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
结果
稍后,我发现
码
1 2 3 4 | 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达到类似的效果,从我的角度来看,这是一种更准确的方法。
码
1 2 3 4 5 | 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) |
结果
以上所有解决方案都不错,但是我最喜欢@Steve和@bejota的解决方案,因为它们不涉及花哨的调用并且具有通用性。
通用的意思是可以与任何类型的轴(包括
1 2 3 | projection = cartopy.crs.UTM(zone='17N') ax = plt.axes(projection=projection) im = ax.imshow(np.arange(200).reshape((20, 10))) |
致电
1 | cax = divider.append_axes("right", size=width, pad=pad) |
将失败,并显示:
因此,使用所有类型的轴处理颜色条大小的唯一通用方法是:
1 | ax.colorbar(im, fraction=0.046, pad=0.04) |
从0.035到0.046的分数工作以获得最佳尺寸。但是,必须调整小数和paddig的值,以使其最适合您的绘图,并且根据色条的方向是垂直位置还是水平方向,它们的值将有所不同。
创建
从文件:
fraction 0.15; fraction of original axes to use for colorbar
shrink 1.0; fraction by which to shrink the colorbar