色条限制不符合plt.courtf中的设置vmin/vmax。如何更明确地设置色条限制?

2024-05-05 09:20:59 发布

您现在位置:Python中文网/ 问答频道 /正文

在使用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()

结果对我来说: enter image description here

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

在这种情况下,我希望最终结果有一个颜色条,范围从0到3。


Tags: importmatplotlib颜色asnpcmpltdelta
2条回答

我们可以通过向colorbar发送标量可映射文件来显式设置colorbar限制。

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))

enter image description here

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

1。一个简单而直接的解决方案

在提供自定义级别的同时使用extend命令:

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()
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()

output method 1

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)

函数中的主要命令对应于千焦在他/她的答案中提出的建议,但是需要更多的行,以通过从contourf对象中提取所有信息来避免所有显式和潜在的错误赋值。

用法:

操作要求从0到3的级别。最深的蓝色表示0以下的值,因此我发现扩展标记很有用。

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()
plt.title('Simplest default with labels')
CS = plt.contourf(X, Y, Z, levels=6, vmin=0.0, vmax=3.0, cmap=cm.coolwarm)

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)
    # boundaries = [vmin]+CS.levels[ (CS.levels>vmin) & (CS.levels<vmax) ].tolist()+[vmax] # fails when vmin<CS.levels.min()
    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)

colorbar = clippedcolorbar(CS)

plt.show()

output

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

output with extend='neither'

相关问题 更多 >