Ответ 1
Во-первых, существует более одного способа сделать это.
- Используйте
colors
kwarg дляcontourf
и вручную укажите цвета - Используйте собственный
Normalize
класс и передайте экземпляр в качествеnorm
kwarg. - Используйте дискретную цветовую карту, созданную с помощью
matplotlib.colors.from_levels_and_colors
.
Самый простой способ - передать определенные цвета с помощью colors=sequence_of_colors
. Однако, если вы не вручную устанавливаете количество контуров, это может быть неудобно.
Наиболее гибким способом является второй вариант: используйте norm
kwarg, чтобы указать обычную нормализацию. Для чего вы хотите, вам нужно подклассом Normalize
, но это не так сложно сделать. Это единственный вариант, который позволяет использовать непрерывную цветокоррекцию.
Причиной использования второго или третьего варианта является то, что они будут работать для любого типа графика matplotlib, который использует цветовой код (например, imshow
, scatter
и т.д.).
Третий вариант создает дискретный цветовой код и объект нормализации из определенных цветов. Он в основном идентичен первому варианту, но он будет: а) работать с другими типами графиков, чем контурные графики, и б) избегать необходимости вручную указывать количество контуров.
В качестве примера второго варианта (я буду использовать imshow
здесь, потому что он имеет больше смысла, чем contourf
для случайных данных, но contourf
будет иметь идентичное использование, отличное от опции interpolation
.):
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()