Python 设置 Matplotlib 颜色条大小以匹配图形
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18195758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Set Matplotlib colorbar size to match graph
提问by Elliot
I cannot get the colorbar on imshow graphs like this one to be the same height as the graph, short of using Photoshop after the fact. How do I get the heights to match?
我无法让像这样的 imshow 图表上的颜色条与图表的高度相同,事后没有使用 Photoshop。如何让高度匹配?
采纳答案by bogatron
You can do this easily with a matplotlib AxisDivider.
您可以使用 matplotlib AxisDivider轻松完成此操作。
The example from the linked page also works without using subplots:
链接页面中的示例也可以在不使用子图的情况下工作:
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)
回答by Steve Barnes
When you create the colorbar
try using the fraction and/or shrink parameters.
当您colorbar
使用分数和/或收缩参数创建尝试时。
From the documents:
从文件:
fraction 0.15; fraction of original axes to use for colorbar
shrink 1.0; fraction by which to shrink the colorbar
分数 0.15; 用于颜色条的原始轴的分数
收缩 1.0;缩小颜色条的分数
回答by skytaker
This combination (and values near to these) seems to "magically" work for me to keep the colorbar scaled to the plot, no matter what size the display.
这种组合(以及接近这些值的值)似乎“神奇地”为我工作,无论显示大小如何,都可以使颜色条与绘图保持一致。
plt.colorbar(im,fraction=0.046, pad=0.04)
It also does not require sharing the axis which can get the plot out of square.
它还不需要共享可以使绘图不规则的轴。
回答by Matthias
@bogatron already gave the answer suggested by the matplotlib docs, which produces the right height, but it introduces a different problem. Now the width of the colorbar (as well as the space between colorbar and plot) changes with the width of the plot. In other words, the aspect ratio of the colorbar is not fixed anymore.
@bogatron 已经给出了matplotlib docs建议的答案,它产生了正确的高度,但它引入了一个不同的问题。现在颜色条的宽度(以及颜色条和绘图之间的空间)随着绘图的宽度而变化。换句话说,颜色条的纵横比不再固定。
To get both the right height anda given aspect ratio, you have to dig a bit deeper into the mysterious axes_grid1
module.
为了获得正确的高度和给定的纵横比,你必须深入挖掘这个神秘的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)
Note that this specifies the widthof the colorbar w.r.t. the heightof the plot (in contrast to the widthof the figure, as it was before).
请注意,这指定了颜色条的宽度与绘图的高度(与之前的图形宽度相反)。
The spacing between colorbar and plot can now be specified as a fraction of the width of the colorbar, which is IMHO a much more meaningful number than a fraction of the figure width.
颜色条和绘图之间的间距现在可以指定为颜色条宽度的一部分,恕我直言,这是一个比图形宽度的一部分更有意义的数字。
UPDATE:
更新:
I created an IPython notebook on the topic, where I packed the above code into an easily re-usable function:
我创建了一个关于主题的 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)
It can be used like this:
它可以像这样使用:
im = plt.imshow(np.arange(200).reshape((20, 10)))
add_colorbar(im)
回答by Bogdan
All the above solutions are good, but I like @Steve's and @bejota's the best as they do not involve fancy calls and are universal.
以上所有解决方案都很好,但我最喜欢 @Steve 和 @bejota,因为它们不涉及花哨的调用并且是通用的。
By universal I mean that works with any type of axes including GeoAxes
. For example, it you have projected axes for mapping:
通用我的意思是适用于任何类型的轴,包括GeoAxes
. 例如,如果您有用于映射的投影轴:
projection = cartopy.crs.UTM(zone='17N')
ax = plt.axes(projection=projection)
im = ax.imshow(np.arange(200).reshape((20, 10)))
a call to
打电话给
cax = divider.append_axes("right", size=width, pad=pad)
will fail with: KeyException: map_projection
将失败: KeyException: map_projection
Therefore, the only universal way of dealing colorbar size with all types of axes is:
因此,处理所有类型轴的颜色条大小的唯一通用方法是:
ax.colorbar(im, fraction=0.046, pad=0.04)
Work with fraction from 0.035 to 0.046 to get your best size. However, the values for the fraction and paddig will need to be adjusted to get the best fit for your plot and will differ depending if the orientation of the colorbar is in vertical position or horizontal.
使用从 0.035 到 0.046 的分数以获得最佳尺寸。但是,需要调整分数和 paddig 的值以获得最适合您的绘图,并且会根据颜色条的方向是垂直位置还是水平位置而有所不同。
回答by Fei Yao
I appreciate all the answers above. However, like some answers and comments pointed out, the axes_grid1
module cannot address GeoAxes, whereas adjusting fraction
, pad
, shrink
, and other similar parameters cannot necessarily give the very precise order, which really bothers me. I believe that giving the colorbar
its own axes
might be a better solution to address all the issues that have been mentioned.
我很欣赏上面的所有答案。然而,像一些答案和评论中指出,该axes_grid1
模块不能地址GeoAxes,而调整fraction
,pad
,shrink
,和其他类似参数不一定能给出非常精确的顺序,这真的令我烦恼。我相信,给出colorbar
自己的axes
可能是解决所有提到的问题的更好的解决方案。
Code
代码
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)
Result
结果
Later on, I find matplotlib.pyplot.colorbar
official documentationalso gives ax
option, which are existing axes that will provide room for the colorbar. Therefore, it is useful for multiple subplots, see following.
后来,我发现matplotlib.pyplot.colorbar
官方文档也提供了ax
选项,这些是现有的轴,将为颜色条提供空间。因此,它对多个子图很有用,请参见下文。
Code
代码
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)
Result
结果
Again, you can also achieve similar effects by specifying cax, a more accurate way from my perspective.
同样,您也可以通过指定 cax 来实现类似的效果,从我的角度来看,这是一种更准确的方法。
Code
代码
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)