Python 颜色条限制与plt.F中的设置vmin/vmax无关。如何更明确地设置颜色栏限制?

Python 颜色条限制与plt.F中的设置vmin/vmax无关。如何更明确地设置颜色栏限制?,python,matplotlib,plot,Python,Matplotlib,Plot,在使用contourf打印时,尝试调整数据范围时得到奇怪的结果 import matplotlib import numpy as np import matplotlib.cm as cm import matplotlib.mlab as mlab import matplotlib.pyplot as plt delta = 0.025 x = np.arange(-3.0, 3.0, delta) y = np.arange(-2.0, 2.0, delta) X, Y = np.me

在使用contourf打印时,尝试调整数据范围时得到奇怪的结果

import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)

plt.figure()
CS = plt.contourf(X, Y, Z, vmin = 0, vmax = 3)
plt.title('Simplest default with labels')
plt.colorbar()

plt.show()
结果对我来说:

这就像颜色与vmin/vmax I设置相匹配,但颜色栏上显示的数字范围保持不变,不设置vmin/vmax


在这种情况下,我希望最终结果的颜色条范围为0到3。

我们可以通过向
颜色条发送可映射的标量来显式设置颜色条限制

CS = plt.contourf(X, Y, Z, 5, vmin = 0., vmax = 2., cmap=cm.coolwarm)
plt.title('Simplest default with labels')
m = plt.cm.ScalarMappable(cmap=cm.coolwarm)
m.set_array(Z)
m.set_clim(0., 2.)
plt.colorbar(m, boundaries=np.linspace(0, 2, 6))

首先,标记为“答案”的回答是错误的(参见我上面的评论),但它帮助我想出了另外两个解决方案

正如JulianBauer在下面的评论中指出的那样,OP使用的函数
mlab.bivariate_normal
不再可用。 为了提供能够产生与其他答案相比较的输出的函数代码,我调用了以下函数,其中的
bivariate_normal
定义复制自:

1。简单明了的解决方案

在提供自定义标高时使用extend命令:

import numpy as np
import matplotlib
import matplotlib.cm as cm
import matplotlib.pyplot as plt

X,Y,Z = myfunction()

plt.figure()
plt.title('Simplest default with labels')
levels = np.linspace(0.0, 3.0, 7)
CS = plt.contourf(X, Y, Z, levels=levels, cmap=cm.coolwarm, extend='min')

colorbar = plt.colorbar(CS)

plt.show()

2。更复杂的解决方案

在上面的答案中提供了,尽管它需要根据具体情况进行调整,并且很容易得到一个色条,其级别与实际绘图中的级别不同。我发现这很危险,所以我尝试将其封装在一个可以在任何上下文中安全调用的函数中:

def clippedcolorbar(CS, **kwargs):
    from matplotlib.cm import ScalarMappable
    from numpy import arange, floor, ceil
    fig = CS.ax.get_figure()
    vmin = CS.get_clim()[0]
    vmax = CS.get_clim()[1]
    m = ScalarMappable(cmap=CS.get_cmap())
    m.set_array(CS.get_array())
    m.set_clim(CS.get_clim())
    step = CS.levels[1] - CS.levels[0]
    cliplower = CS.zmin<vmin
    clipupper = CS.zmax>vmax
    noextend = 'extend' in kwargs.keys() and kwargs['extend']=='neither'
    # set the colorbar boundaries
    boundaries = arange((floor(vmin/step)-1+1*(cliplower and noextend))*step, (ceil(vmax/step)+1-1*(clipupper and noextend))*step, step)
    kwargs['boundaries'] = boundaries
    # if the z-values are outside the colorbar range, add extend marker(s)
    # This behavior can be disabled by providing extend='neither' to the function call
    if not('extend' in kwargs.keys()) or kwargs['extend'] in ['min','max']:
        extend_min = cliplower or ( 'extend' in kwargs.keys() and kwargs['extend']=='min' )
        extend_max = clipupper or ( 'extend' in kwargs.keys() and kwargs['extend']=='max' )
        if extend_min and extend_max:
            kwargs['extend'] = 'both'
        elif extend_min:
            kwargs['extend'] = 'min'
        elif extend_max:
            kwargs['extend'] = 'max'
    return fig.colorbar(m, **kwargs)

可以通过调用
clippedcolorbar(CS,extend='note')
而不是
clippedcolorbar(CS)
来禁用扩展标记


这是预期的结果;低于colornormalization的值将以最低的colormap颜色着色。您的问题缺少问题描述。您希望实现什么?为清晰起见进行了编辑。在本例中,我希望最终结果的颜色栏范围为0到3。我的问题是颜色栏没有被分割成不同的级别。@user3826115我更改了答案。我现在把
bounders=np.arange(0,3.1,5)
发送到
colorbar
。我认为这个答案是错误的!根据颜色栏,对应于最高值的面片包含范围为1.5到2.0的值。但是,它的形状比上图中的相应区域小。另外,还有一个蓝色的灰色色调,我在颜色栏里看不出来。@Bastian谢谢你指出这一点。基础数据的最大值小于3,但我将颜色最大值设置为3。我随意选择了颜色栏中的垃圾箱。我更新了我的示例,以便颜色栏中的颜色和填充轮廓这次匹配。@kilojoules您的响应仍然包含错误
Z.max()。此外,绘图和颜色栏中的颜色不匹配。看起来绘图中有4种蓝色(不包括灰色),但颜色栏中有3种。@kilojoules touché,我在某个地方出错了。我明天会看一看。谢谢你指出。是的!此外,颜色条值的间隔不均匀,这是我认为OP需要的。间隔不均匀是因为我忘记更新图像。@Bastian由于删除了
mlab.bivariate_normal
,您的示例不再有效(请参阅)。最小的选择是
Z=X-Y
def clippedcolorbar(CS, **kwargs):
    from matplotlib.cm import ScalarMappable
    from numpy import arange, floor, ceil
    fig = CS.ax.get_figure()
    vmin = CS.get_clim()[0]
    vmax = CS.get_clim()[1]
    m = ScalarMappable(cmap=CS.get_cmap())
    m.set_array(CS.get_array())
    m.set_clim(CS.get_clim())
    step = CS.levels[1] - CS.levels[0]
    cliplower = CS.zmin<vmin
    clipupper = CS.zmax>vmax
    noextend = 'extend' in kwargs.keys() and kwargs['extend']=='neither'
    # set the colorbar boundaries
    boundaries = arange((floor(vmin/step)-1+1*(cliplower and noextend))*step, (ceil(vmax/step)+1-1*(clipupper and noextend))*step, step)
    kwargs['boundaries'] = boundaries
    # if the z-values are outside the colorbar range, add extend marker(s)
    # This behavior can be disabled by providing extend='neither' to the function call
    if not('extend' in kwargs.keys()) or kwargs['extend'] in ['min','max']:
        extend_min = cliplower or ( 'extend' in kwargs.keys() and kwargs['extend']=='min' )
        extend_max = clipupper or ( 'extend' in kwargs.keys() and kwargs['extend']=='max' )
        if extend_min and extend_max:
            kwargs['extend'] = 'both'
        elif extend_min:
            kwargs['extend'] = 'min'
        elif extend_max:
            kwargs['extend'] = 'max'
    return fig.colorbar(m, **kwargs)
import numpy as np
import matplotlib
import matplotlib.cm as cm
import matplotlib.pyplot as plt

X,Y,Z = myfunction()

plt.figure()
plt.title('Simplest default with labels')
CS = plt.contourf(X, Y, Z, levels=6, vmin=0.0, vmax=3.0, cmap=cm.coolwarm)

colorbar = clippedcolorbar(CS)

plt.show()