颜色条限制不考虑 plt.contourf 中的 vmin/vmax 设置。如何更明确地设置颜色条限制?

hm8*_*hm8 16 python plot matplotlib

使用轮廓绘制时尝试调整数据范围时得到奇怪的结果

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()
Run Code Online (Sandbox Code Playgroud)

结果对我来说: 在此处输入图片说明

就像颜色与我设置的 vmin/vmax 相匹配,但颜色栏上显示的数字范围仍然是没有设置 vmin/vmax 的情况。

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

Bas*_*ian 16

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

正如 JulianBauer 在下面的评论中指出的那样,mlab.bivariate_normalOP 使用的功能不再可用。为了提供产生可以与其他答案进行比较的输出的功能代码,我正在调用以下函数,其定义是bivariate_normalmatplotlib 存储库复制的:

def myfunction():

    def bivariate_normal(X, Y, sigmax=1.0, sigmay=1.0, mux=0.0, muy=0.0, sigmaxy=0.0):
        """copied from here: https://github.com/matplotlib/matplotlib/blob/81e8154dbba54ac1607b21b22984cabf7a6598fa/lib/matplotlib/mlab.py#L1866"""
        Xmu = X-mux
        Ymu = Y-muy
        rho = sigmaxy/(sigmax*sigmay)
        z = Xmu**2/sigmax**2 + Ymu**2/sigmay**2 - 2*rho*Xmu*Ymu/(sigmax*sigmay)
        denom = 2*np.pi*sigmax*sigmay*np.sqrt(1-rho**2)
        return np.exp(-z/(2*(1-rho**2))) / denom

    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 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
    Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
    Z = 10.0 * (Z2 - Z1)
    return X,Y,Z
Run Code Online (Sandbox Code Playgroud)

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

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

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()
Run Code Online (Sandbox Code Playgroud)

输出方法一

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)
Run Code Online (Sandbox Code Playgroud)

函数中的主要命令对应于他/她的答案中提出的千焦耳,但需要更多的行来通过从contourf对象中提取所有信息来避免所有明确的和潜在的错误分配。

用法:

OP 要求从 0 到 3 的级别。最深的蓝色代表低于 0 的值,因此我发现扩展标记很有用。

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

Run Code Online (Sandbox Code Playgroud)

输出

可以通过调用clippedcolorbar(CS, extend='neither')代替来禁用扩展标记clippedcolorbar(CS)

输出与扩展 =“都没有”


kil*_*les 8

我们可以通过发送一个可映射的标量到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))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

编辑

有关完整解决方案,请参阅巴斯蒂安的回答。我的方法的问题是颜色条的段与等高线图的段不对应。它们使用相同的色标,但等高线图和色条以不同的方式划分色标。使用正确的下限/上限,此解决方案提供 6 个级别的等高线图和 6 个级别的颜色条。由于等高线图和颜色条有不同的边界,所以颜色段不同。

  • **我认为这个答案是错误的!** 最高值对应的补丁包含根据颜色条从 1.5 到 2.0 范围内的值。然而,它的形状比上图中的相应区域小。另外,图中还有一种灰色的蓝色调,我在颜色条中无法识别。 (4认同)