我无法让像这样的imshow
图形上的colorbar
与图形本身具有相同的高度,除非事后使用Photoshop。如何使它们的高度匹配?
我无法让像这样的imshow
图形上的colorbar
与图形本身具有相同的高度,除非事后使用Photoshop。如何使它们的高度匹配?
这个组合(或接近这些值)似乎在任何显示屏大小下都能“神奇地”使色条与图形按比例缩放。
plt.colorbar(im,fraction=0.046, pad=0.04)
它还不需要共享轴,这可以使图形不成正方形。
im_ratio = data.shape[0]/data.shape[1]
plt.colorbar(im,fraction=0.046*im_ratio, pad=0.04)
其中,data
是你的图像。 - eindzlshrink
关键字参数默认为 1.0
,可以用于进一步微调。当我有两个并排的正方形子图时,发现将 shrink=0.9
能够帮助我得到最佳效果。 - vanPelt2您可以使用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)
plt.title
。这将至少使标题居中于主图上... - S.A.感谢以上所有的回答。然而,像一些回答和评论指出的那样,axes_grid1
模块无法处理GeoAxes,而调整fraction
、pad
、shrink
和其他类似参数也不能确保非常精确的顺序,这真的让我困扰不已。我相信为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)
ax=
轴高度相同”成为一个功能真的很令人沮丧,并且需要像这样降到低级别的图/轴操作。 - shadowtalkerax.inset_axes
创建“子轴”,而不是使用fig.add_axes
创建独立的轴:https://matplotlib.org/stable/gallery/subplots_axes_and_figures/colorbar_placement.html - shadowtalker@bogatron已经给出了由matplotlib文档建议的答案,它可以产生正确的高度,但它引入了不同的问题。现在colorbar的宽度(以及colorbar和图之间的空间)随着图的宽度而变化。换句话说,colorbar的纵横比不再固定。
要同时获得正确的高度和给定的纵横比,您需要更深入地了解神秘的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)
current_ax
替换为您想要添加颜色条的子图的轴即可。 - lightalchemist以上所有解决方案都很好,但我最喜欢@Steve和@bejota的解决方案,因为它们不涉及花哨的调用,并且是通用的。
通用的意思是可以与任何类型的轴一起使用,包括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
和pad
不能产生足够的期望结果时,我们还可以添加shrink
参数。 - Fei Yao当您创建colorbar
时,请尝试使用分数和/或收缩参数。
根据文档:
fraction 0.15; 用于colorbar的原始轴的分数
shrink 1.0; colorbar要缩小的比例
colorbar()
函数或方法的参数? - Steve Barnes另一个选择是
shrink=0.7, aspect=20*0.7
shrink
会缩小高度和宽度,但aspect
参数会恢复原始宽度。默认的宽高比是20。0.7
是经过实证确定的。
我最近遇到了这个问题,我使用ax.twinx()
来解决它。例如:
from matplotlib import pyplot as plt
# Some other code you've written
...
# Your data generation goes here
xdata = ...
ydata = ...
colordata = function(xdata, ydata)
# Your plotting stuff begins here
fig, ax = plt.subplots(1)
im = ax.scatterplot(xdata, ydata, c=colordata)
# Create a new axis which will be the parent for the colour bar
# Note that this solution is independent of the 'fig' object
ax2 = ax.twinx()
ax2.tick_params(which="both", right=False, labelright=False)
# Add the colour bar itself
plt.colorbar(im, ax=ax2)
# More of your code
...
plt.show()
在创建需要调用matplotlib的Axes
对象作为参数并对其进行绘制并返回该对象的函数时,我发现这特别有用,因为我不需要传入单独从figure
对象生成的轴或传递figure
对象本身。
axes_grid1.axes_divider
是此任务的指定方法(甚至在 matplotlib 中有 演示文稿),但通过添加 colorbar,会使图像变小。 如果要保留原始图像大小,那么以下提供了一种方法(基于Fei Yao的答案)。
data = [(1,2,3,4,5),(4,5,6,7,8),(7,8,9,10,11)]
im = plt.imshow(data, cmap='RdBu')
l, b, w, h = plt.gca().get_position().bounds
cax = plt.gcf().add_axes([l + w + 0.03, b, 0.03, h])
plt.colorbar(im, cax=cax)
import matplotlib.pyplot as plt
def add_colorbar(im, width=None, pad=None, **kwargs):
l, b, w, h = im.axes.get_position().bounds # get boundaries
width = width or 0.1 * w # get width of the colorbar
pad = pad or width # get pad between im and cbar
fig = im.axes.figure # get figure of image
cax = fig.add_axes([l + w + pad, b, width, h]) # define cbar Axes
return fig.colorbar(im, cax=cax, **kwargs) # draw cbar
data = [(1,2,3,4,5),(4,5,6,7,8),(7,8,9,10,11)]
# an example usage
im = plt.imshow(data, cmap='RdBu')
add_colorbar(im)
如果您不想声明另一组坐标轴,我发现最简单的解决方案是使用figsize调用更改图形大小。
在上面的示例中,我会从以下内容开始
fig = plt.figure(figsize = (12,6))
然后只需以不同的比例重新渲染,直到色条不再使主图变得微不足道。