我正在尝试为数据集创建填充轮廓。它应该相当简单:
plt.contourf(x, y, z, label = 'blah', cm = matplotlib.cm.RdBu)
但是,如果我的数据集关于0不对称,我该怎么办?假设我想从蓝色(负值)变为0(白色)到红色(正值)。如果我的数据集从-8变为3,那么颜色条的白色部分(应该为0)实际上是略微负的。有没有办法改变颜色条?
答案 0 :(得分:37)
首先,有多种方法可以做到这一点。
colors
kwarg contourf
并手动指定颜色Normalize
类并将实例作为norm
kwarg传递。matplotlib.colors.from_levels_and_colors
构建的离散色图。最简单的方法是使用colors=sequence_of_colors
传递特定颜色。但是,如果您没有手动设置轮廓的数量,这可能会很不方便。
最灵活的方法是第二种选择:使用norm
kwarg指定自定义规范化。对于你想要的东西,你需要继承Normalize
,但这并不难。这是允许您使用连续色彩映射的唯一选项。
使用第二个或第三个选项的原因是它们适用于使用色彩图的任何类型的matplotlib图(例如imshow
,scatter
等)。
第三个选项根据特定颜色构造离散色图和标准化对象。它与第一个选项基本相同,但它将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()
作为第三个选项的示例(请注意,这会提供离散的色彩映射而不是连续的色彩映射):
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()