matplotlib bwr colormap,始终以z为中心

2024-10-09 18:17:01 发布

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

我试图用正数和负数绘制一个矩阵。数字将在-1到1之间的间隔内,但不在整个范围内。例如,数字有时可能在-0.2到+0.8之间(参见下面的代码)。 我想使用bwr颜色映射(蓝色->;白色-红色),这样零总是用白色进行颜色编码。-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()

这段代码创建的图形可以在这里看到:figure create with posted code

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

编辑: 在深入研究了一段时间之后,我自己找到了一个令人满意的答案,不是触摸colormap,而是使用可选输入pcolor(见下文)。 不过,我不会删除这个问题,因为在我发布这个问题并点击相关的问题/答案之前,我找不到答案。另一方面,我不介意它是否被删除,因为如果你正在寻找合适的关键字,这个问题的答案可以在其他地方找到。


Tags: theto答案代码fromnumpy编码plot
3条回答

还可以使用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

它产生了这个数字: enter image description here

可以使用matplotlib.colors.diveringnorm,如下所示:

# define your scale, with white at zero
vmin = -0.2 
vmax = 0.8
norm = colors.DivergingNorm(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.DivergingNorm(vmin=vmin, vcenter=0, vmax=vmax)

plt.pcolor(X, Y, Z, vmin=vmin, vmax=vmax, norm=norm)   
plt.colorbar()

会给你:

enter image description here

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

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

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

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

相关问题 更多 >

    热门问题