移位色板matplotlib [英] Shifted colorbar matplotlib
问题描述
我想为一个数据集填充轮廓。应该很简单:
I am trying to make a filled contour for a dataset. It should be fairly straightforward:
plt.contourf(x, y, z, label = 'blah', cm = matplotlib.cm.RdBu)
但是,如果我的数据集对称不是0,我该怎么办?假设我想从蓝色(负值)到0(白色),到红色(正值)。如果我的数据集从-8到3,那么颜色条的白色部分,应该在0,实际上是略负。是否有一些方法来改变颜色条?
However, what do I do if my dataset is not symmetric about 0? Let's say I want to go from blue (negative values) to 0 (white), to red (positive values). If my dataset goes from -8 to 3, then the white part of the color bar, which should be at 0, is in fact slightly negative. Is there some way to shift the color bar?
推荐答案
首先,有多种方法可以做到这一点。
First off, there's more than one way to do this.
- 使用
颜色
kwarg至contourf
并手动指定颜色 - 使用自定义
Normalize
类并传递一个实例作为norm
kwarg。 - 使用由
matplotlib.colors.from_levels_and_colors
构成的离散色彩映射
- Use the
colors
kwarg tocontourf
and manually specify the colors - Use a custom
Normalize
class and pass an instance in as thenorm
kwarg. - Use a discrete colormap constructed with
matplotlib.colors.from_levels_and_colors
.
最简单的方法是传递 colors = sequence_of_colors
的特定颜色。但是,如果您不手动设置轮廓数,这可能不方便。
The simplest way is to pass in specific colors with colors=sequence_of_colors
. However, if you're not manually setting the number of contours, this can be inconvenient.
最灵活的方式是第二个选项:使用 norm
kwarg指定自定义规范化。对于你想要的,你需要子类 Normalize
,但这不是太难做。这是唯一允许您使用连续色彩映射的选项。
The most flexible way is the second option: use the norm
kwarg to specify a custom normalization. For what you're wanting, you'll need to subclass Normalize
, but this isn't too hard to do. This is the only option that allows you to use a continuous colormap.
使用第二个或第三个选项的原因是它们将适用于任何类型的matplotlib图使用颜色映射(例如 imshow
, scatter
等)。
The reason to use the second or third options is that they will work for any type of matplotlib plot that uses a colormap (e.g. imshow
, scatter
, etc).
第三个选项根据特定颜色构造离散色彩映射和规范化对象。它基本上与第一个选项相同,但它将a)与等值线图一起使用其他类型的图,以及b)避免必须手动指定轮廓数。
The third option constructs a discrete colormap and normalization object from specific colors. It's basically identical to the first option, but it will a) work with other types of plots than contour plots, and b) avoids having to manually specify the number of contours.
作为第二个选项的例子(我将在这里使用 imshow
,因为它比随机的 contourf
更有意义数据,但 contourf
将具有与插值
选项不同的用法。):
As an example of the second option (I'll use imshow
here because it makes more sense than contourf
for random data, but contourf
would have identical usage other than the interpolation
option.):
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()
作为第三个选项的示例注意这给出了离散色彩映射,而不是连续色彩映射):
As an example of the third option (notice that this gives a discrete colormap instead of a continuous colormap):
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()
这篇关于移位色板matplotlib的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!