Як я можу побудувати значення 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?
yukashima huksay

2
@yukashimahuksay: так, але вам потрібно було б замаскувати ці цінності. Напр. arr = np.ma.array(arr, mask=(arr == 0)).
Arcturus B

Я думаю, що "c" у "cmap" вже означає "поточний", тому я б не називав змінну "current_cmap"
Т. Гвен,

3
@TGwen: Я майже впевнений, що cmap розшифровується як colormap, що і є терміном, який використовується в документі: matplotlib.org/api/cm_api.html#matplotlib.cm.get_cmap
Arcturus B

82

Hrm, здається, я можу використовувати замаскований масив для цього:

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). Крім того, якщо ви хочете встановити 0-значення для іншого кольору, щось на зразок 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.