Как я могу отобразить значения NaN как специальный цвет с помощью imshow в matplotlib?

85

Я пытаюсь использовать imshow в matplotlib для построения данных в виде тепловой карты, но некоторые из значений являются NaN. Я бы хотел, чтобы NaN отображались как особый цвет, которого нет в цветовой карте.

пример:

import numpy as np
import matplotlib.pyplot as plt
f = plt.figure()
ax = f.add_subplot(111)
a = np.arange(25).reshape((5,5)).astype(float)
a[3,:] = np.nan
ax.imshow(a, interpolation='nearest')
f.canvas.draw()

Результирующее изображение неожиданно становится полностью синим (самый низкий цвет на карте цветов струи). Однако, если я сделаю такой график:

ax.imshow(a, interpolation='nearest', vmin=0, vmax=24)

- тогда я получаю что-то получше, но значения NaN отображаются того же цвета, что и vmin ... Есть ли изящный способ, которым я могу настроить отображение NaN особым цветом (например, серым или прозрачным)?

Адам Фрейзер
источник
Несколько лет спустя ( matplotlib.__version__=='1.2.1') это работает без проблем.
Frédéric Grosshans

Ответы:

46

В более новых версиях Matplotlib больше нет необходимости использовать замаскированный массив.

Например, давайте сгенерируем массив, в котором каждое 7-е значение является NaN:

arr = np.arange(100, dtype=float).reshape(10, 10)
arr[~(arr % 7).astype(bool)] = np.nan

Мы можем изменить текущую цветовую карту и построить массив со следующими строками:

current_cmap = matplotlib.cm.get_cmap()
current_cmap.set_bad(color='red')
plt.imshow(arr)

результат сюжета

Арктур ​​Б
источник
можно ли использовать 0 вместо np.nan?
юкашима хуксай 08
2
@yukashimahuksay: да, но вам нужно замаскировать эти значения. Например. arr = np.ma.array(arr, mask=(arr == 0)).
Arcturus B
Я думаю, что 'c' в 'cmap' уже означает 'current', поэтому я бы не стал называть переменную 'current_cmap'
Т. Гвен
3
@TGwen: Я почти уверен, что cmap означает цветовую карту, этот термин используется в документе: matplotlib.org/api/cm_api.html#matplotlib.cm.get_cmap
Arcturus B
82

Хм, похоже, я могу использовать для этого замаскированный массив:

masked_array = np.ma.array (a, mask=np.isnan(a))
cmap = matplotlib.cm.jet
cmap.set_bad('white',1.)
ax.imshow(masked_array, interpolation='nearest', cmap=cmap)

Этого должно быть достаточно, хотя я все еще открыт для предложений. :]

Адам Фрейзер
источник
Это определенно помогает. Официальные документы больше ничего не показывают.
Agos
6
Побочным точка - Я думаю , что делать это будет переопределить значение по умолчанию matplotlib.cm.jet, так что я обычно делаю копию: import copy; cmap=copy.copy(matplotlib.cm.jet). Кроме того, если вы хотите установить нулевые значения для другого цвета, cmap._init(); cm._lut[:,0] = (1,1,1,1)должно работать что-то вроде .
keflavich
3
Также есть set_overи set_underдля контроля окраски значений вне диапазона. Поведение по умолчанию - соответствие верху / низу цветового диапазона.
tacaswell
2
Ли masked_arrayтребуется вообще? Если aсодержит значения NaN (так кажется mask=np.isnan(a)), то простое imshowдобавление массива aс настроенной картой cmapотобразит NaN-ячейки нужного цвета (белый). Так что у меня это работает. Есть ли исключения?
MaciekS
2
@MaciekS, при использовании расходящейся цветовой карты вы не хотите, чтобы ваши nanзначения и медианные значения отображались одного цвета, например белого.
AGS