移位的colorbar matplotlib

时间:2013-11-22 12:06:32

标签: python colors matplotlib

我正在尝试为数据集创建填充轮廓。它应该相当简单:

plt.contourf(x, y, z, label = 'blah', cm = matplotlib.cm.RdBu)

但是,如果我的数据集关于0不对称,我该怎么办?假设我想从蓝色(负值)变为0(白色)到红色(正值)。如果我的数据集从-8变为3,那么颜色条的白色部分(应该为0)实际上是略微负的。有没有办法改变颜色条?

1 个答案:

答案 0 :(得分:37)

首先,有多种方法可以做到这一点。

  1. 使用colors kwarg contourf并手动指定颜色
  2. 使用自定义Normalize类并将实例作为norm kwarg传递。
  3. 使用由matplotlib.colors.from_levels_and_colors构建的离散色图。
  4. 最简单的方法是使用colors=sequence_of_colors传递特定颜色。但是,如果您没有手动设置轮廓的数量,这可能会很不方便。

    最灵活的方法是第二种选择:使用norm kwarg指定自定义规范化。对于你想要的东西,你需要继承Normalize,但这并不难。这是允许您使用连续色彩映射的唯一选项。

    使用第二个或第三个选项的原因是它们适用于使用色彩图的任何类型的matplotlib图(例如imshowscatter等)。

    第三个选项根据特定颜色构造离散色图和标准化对象。它与第一个选项基本相同,但它将a)使用除轮廓图之外的其他类型的图,并且b)避免必须手动指定轮廓的数量。

    作为第二个选项的示例(我将在此处使用imshow,因为它对于随机数据比contourf更有意义,但contourf除了{interpolation之外具有相同的用法{1}}选项。):

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.colors import Normalize
    
    class MidpointNormalize(Normalize):
        def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
            self.midpoint = midpoint
            Normalize.__init__(self, vmin, vmax, clip)
    
        def __call__(self, value, clip=None):
            # I'm ignoring masked values and all kinds of edge cases to make a
            # simple example...
            x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
            return np.ma.masked_array(np.interp(value, x, y))
    
    data = np.random.random((10,10))
    data = 10 * (data - 0.8)
    
    fig, ax = plt.subplots()
    norm = MidpointNormalize(midpoint=0)
    im = ax.imshow(data, norm=norm, cmap=plt.cm.seismic, interpolation='none')
    fig.colorbar(im)
    plt.show()
    

    enter image description here

    作为第三个选项的示例(请注意,这会提供离散的色彩映射而不是连续的色彩映射):

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.colors import from_levels_and_colors
    
    data = np.random.random((10,10))
    data = 10 * (data - 0.8)
    
    num_levels = 20
    vmin, vmax = data.min(), data.max()
    midpoint = 0
    levels = np.linspace(vmin, vmax, num_levels)
    midp = np.mean(np.c_[levels[:-1], levels[1:]], axis=1)
    vals = np.interp(midp, [vmin, midpoint, vmax], [0, 0.5, 1])
    colors = plt.cm.seismic(vals)
    cmap, norm = from_levels_and_colors(levels, colors)
    
    fig, ax = plt.subplots()
    im = ax.imshow(data, cmap=cmap, norm=norm, interpolation='none')
    fig.colorbar(im)
    plt.show()
    

    enter image description here