【问题标题】:matplotlib bwr-colormap, always centered on zeromatplotlib bwr-colormap,总是以零为中心
【发布时间】:2014-10-19 11:12:47
【问题描述】:

我正在尝试绘制一个包含正数和负数的矩阵。这些数字将在 -1 到 1 的区间内,但不在完整范围内。例如,数字有时可能在 -0.2 到 +0.8 的范围内(参见下面的代码)。 我想使用 bwr-colormap (blue -> white - red),这样零总是用白色进行颜色编码。 -1 应该用最深的蓝色进行颜色编码,+1 应该用最深的红色进行颜色编码。这里有一个例子,两个图只能通过颜色条来区分。

import numpy
from matplotlib import pyplot as plt

# some arbitrary data to plot
x = numpy.linspace(0, 2*numpy.pi, 30)
y = numpy.linspace(0, 2*numpy.pi, 20)
[X, Y] = numpy.meshgrid(x, y)
Z = numpy.sin(X)*numpy.cos(Y)

fig = plt.figure()
plt.ion()
plt.set_cmap('bwr') # a good start: blue to white to red colormap

# a plot ranging from -1 to 1, hence the value 0 (the average) is colorcoded in white
ax = fig.add_subplot(1, 2, 1)
plt.pcolor(X, Y, Z)
plt.colorbar()

# a plot ranging from -0.2 to 0.8 hence 0.3 (the average) is colorcoded in white
ax = fig.add_subplot(1, 2, 2)
plt.pcolor(X, Y, Z*0.5 + 0.3)   # rescaled Z-Data
plt.colorbar()

这段代码创建的图可以看这里:

如上所述,我正在寻找一种始终使用相同颜色对值进行颜色编码的方法,其中 -1:深蓝色,0:白色,+1:深红色。这是一个单行字,我错过了什么还是我必须自己为此写一些东西?

编辑: 在挖掘了一点点之后,我自己找到了一个令人满意的答案,没有触摸颜色图,而是使用pcolor 的可选输入(见下文)。 不过,我不会删除该问题,因为在我发布此问题并单击相关问题/答案之前,我无法在 SO 上找到答案。另一方面,如果它被删除,我不介意,因为如果您正在寻找正确的关键字,可以在其他地方找到这个问题的答案。

【问题讨论】:

    标签: python matplotlib colors


    【解决方案1】:

    显然,我在挖掘了一段时间后自己找到了答案。 pcolor 提供可选输入 vminvmax。如果我分别将它们设置为 -1 和 1,它正好解决了这个问题。然后,颜色编码似乎与 vmin 和 vmax 相关,而不是与绘制的数据的最小值和最大值相关。因此将绘图命令(和 cmets)更改为

    # a plot ranging from -1 to 1, where the value 0 is colorcoded in white
    ax = fig.add_subplot(1, 2, 1)
    plt.pcolor(X, Y, Z, vmin=-1, vmax=1) # vmin, vmax not needed here
    plt.colorbar()
    
    # a plot ranging from -0.2 to 0.8, where the value 0 is colorcoded in white
    ax = fig.add_subplot(1, 2, 2)
    plt.pcolor(X, Y, Z*0.5 + 0.3, vmin=-1, vmax=1)   # rescaled Z-Data
    plt.colorbar()
    

    它会根据我的需要生成一个图形:

    所以,设置 vmin=-1, vmax=1 就可以了,我不必更改颜色图本身的内容。

    【讨论】:

    • 很高兴您解决了这个问题,但我想指出,只有当正范围设置为与负范围相同时,这才会发生。不过,this question 上的这个问题有很多答案,这些都是很好的方法。
    • @Ajean 我在寻找问题/答案时没有找到。幸运的是,约束vmin == -vmax 对我来说是正确的,我完成了这个问题的工作,因为我对结果很满意。如果我再次遇到这个问题,我现在知道在哪里寻找答案(-:。这有点令人沮丧,因为我知道 python 和 python 绘图,而且我确切地知道如何在 matlab 中解决我的问题。 ..
    【解决方案2】:

    您还可以使用matplotlib.colors 以0 作为中点来规范化数据,以增强图形的拟态值和最大值。如需更多信息,请访问Colormap Norms,您可以查看更多详细信息。

    import matplotlib.colors as colors
    # Example of making your own norm.  Also see matplotlib.colors.
    # From Joe Kington: This one gives two different linear ramps:
    
    class MidpointNormalize(colors.Normalize):
        def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
            self.midpoint = midpoint
            colors.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 numpy.ma.masked_array(numpy.interp(value, x, y))
    #####
    
    # a plot ranging from -0.2 to 0.8 hence 0.3 (the average) is colorcoded in white
    ax = fig.add_subplot(1, 2, 2)
    plt.pcolor(X, Y, Z*0.5 + 0.3, norm=MidpointNormalize(midpoint=0))   # Set midpoint as 0
    plt.colorbar(extend='min') # To extend colorbar in the min values
    plt.subplots_adjust(left=0.125, bottom=0.1, right=0.9, top=0.95, wspace=0.5, hspace=0.1) # to adjust the subplots
    

    它产生这个数字:

    【讨论】:

      【解决方案3】:

      您可以像这样使用 matplotlib.colors.TwoSlopeNorm:

      # define your scale, with white at zero
      vmin = -0.2 
      vmax = 0.8
      norm = colors.TwoSlopeNorm(vmin=vmin, vcenter=0, vmax=vmax)
      

      在你的例子中,

      import numpy
      from matplotlib import pyplot as plt
      
      # some arbitrary data to plot
      x = numpy.linspace(0, 2*numpy.pi, 30)
      y = numpy.linspace(0, 2*numpy.pi, 20)
      [X, Y] = numpy.meshgrid(x, y)
      Z = numpy.sin(X)*numpy.cos(Y)
      
      fig = plt.figure()
      plt.ion()
      plt.set_cmap('bwr') # a good start: blue to white to red colormap
      
      # a plot ranging from -1 to 1, hence the value 0 (the average) is colorcoded in white
      ax = fig.add_subplot(1, 2, 1)
      plt.pcolor(X, Y, Z)
      plt.colorbar()
      
      # a plot ranging from -0.2 to 0.8 hence 0.3 (the average) is colorcoded in white
      ax = fig.add_subplot(1, 2, 2)
      
      # define your scale, with white at zero
      vmin = -0.2 
      vmax = 0.8
      norm = colors.TwoSlopeNorm(vmin=vmin, vcenter=0, vmax=vmax)
      
      plt.pcolor(X, Y, Z, vmin=vmin, vmax=vmax, norm=norm)   
      plt.colorbar()
      

      会给你:

      【讨论】:

      • DivergingNorm 已弃用。较新的代码应该改用TwoSlopeNorm
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-29
      • 2014-11-15
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      • 2017-05-14
      相关资源
      最近更新 更多