Jak mogę wykreślić wartości NaN jako specjalny kolor za pomocą imshow w matplotlib?

85

Próbuję użyć imshow w matplotlib do wykreślenia danych jako mapy cieplnej, ale niektóre wartości to NaN. Chciałbym, aby NaN były renderowane jako specjalny kolor, którego nie ma w mapie kolorów.

przykład:

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()

Powstały obraz jest nieoczekiwanie cały niebieski (najniższy kolor na mapie kolorów odrzutowca). Jeśli jednak robię wykres w ten sposób:

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

- wtedy dostaję coś lepszego, ale wartości NaN są rysowane w tym samym kolorze co vmin ... Czy istnieje wdzięczny sposób, aby ustawić NaN tak, aby były rysowane w specjalnym kolorze (np.: szary lub przezroczysty)?

Adam Fraser
źródło
Kilka lat później ( matplotlib.__version__=='1.2.1') działa to bez problemu.
Frédéric Grosshans,

Odpowiedzi:

46

W nowszych wersjach Matplotlib nie jest już konieczne używanie zamaskowanej tablicy.

Na przykład, wygenerujmy tablicę, w której każda siódma wartość to NaN:

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

Możemy zmodyfikować aktualną mapę kolorów i wykreślić tablicę za pomocą następujących linii:

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

wynik wykresu

Arcturus B
źródło
czy można użyć 0 zamiast np.nan?
yukashima huksay
2
@yukashimahuksay: tak, ale musisz zamaskować te wartości. Na przykład. arr = np.ma.array(arr, mask=(arr == 0)).
Arcturus B
Myślę, że „c” w „cmap” oznacza już „bieżący”, więc nie nazwałbym zmiennej „current_cmap”
T. Gwen,
3
@TGwen: Jestem prawie pewien, że cmap oznacza Colormap, czyli termin używany w dokumencie: matplotlib.org/api/cm_api.html#matplotlib.cm.get_cmap
Arcturus B
82

Hrm, wygląda na to, że mogę użyć do tego zamaskowanej tablicy:

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)

To powinno wystarczyć, chociaż nadal jestem otwarty na sugestie. :]

Adam Fraser
źródło
To zdecydowanie załatwia sprawę. Oficjalne dokumenty nie pokazują nic więcej.
Agos
6
Punkt boku - Myślę, że w ten sposób będzie przesłonić domyślne matplotlib.cm.jet, więc zazwyczaj wykonać kopię: import copy; cmap=copy.copy(matplotlib.cm.jet). Ponadto, jeśli chcesz ustawić wartości 0 na inny kolor, coś takiego cmap._init(); cm._lut[:,0] = (1,1,1,1)powinno działać.
keflavich
3
Istnieje również set_overi set_underdo kontrolowania kolorowania wartości spoza zakresu. Domyślnym zachowaniem jest dopasowanie górnej / dolnej części zakresu kolorów.
tacaswell
2
Czy jest to masked_arrayw ogóle wymagane? Jeśli azawiera wartości NaN (tak się wydaje mask=np.isnan(a)), to samo imshowustawienie tablicy az dostosowaną mapą cmapspowoduje wyświetlenie komórek NaN w wymaganym kolorze (białym). Więc to działa dla mnie. Czy są jakieś wyjątki?
MaciekS
2
@MaciekS, używając rozbieżnej mapy kolorów, nie chcesz, aby Twoje nanwartości i wartości mediany były wykreślane tym samym kolorem, np. Białym.
AGS