Tracciare una mappa di calore 2D con Matplotlib


139

Usando Matplotlib, voglio tracciare una mappa di calore 2D. I miei dati sono un array Numpy n-by-n, ciascuno con un valore compreso tra 0 e 1. Quindi per l'elemento (i, j) di questo array, voglio tracciare un quadrato sulla coordinata (i, j) nel mio mappa termica, il cui colore è proporzionale al valore dell'elemento nella matrice.

Come posso fare questo?


2
hai guardato la matplotlibgalleria prima di pubblicare? Ci sono alcuni esempi di buone utilizzando imshow, pcolore pcolormeshche fanno ciò che si vuole
tmdavison

Risposte:


187

La imshow()funzione con parametri interpolation='nearest'e cmap='hot'dovrebbe fare quello che vuoi.

import matplotlib.pyplot as plt
import numpy as np

a = np.random.random((16, 16))
plt.imshow(a, cmap='hot', interpolation='nearest')
plt.show()

inserisci qui la descrizione dell'immagine


1
Non credo sia necessario specificare l'interpolazione.
miguel.martin,

2
@ miguel.martin secondo il documento di pyplot: "Se l'interpolazione è Nessuna (il suo valore predefinito), l'impostazione predefinita è rc image.interpolation". Quindi penso che sia necessario includerlo.
P. Camilleri,

@ P.Camilleri Come ridimensionare gli assi X e Y? (Cambia solo i numeri, nessuno zoom).
Dole,

64

Seaborn si occupa di gran parte del lavoro manuale e traccia automaticamente una sfumatura sul lato della carta, ecc.

import numpy as np
import seaborn as sns
import matplotlib.pylab as plt

uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data, linewidth=0.5)
plt.show()

inserisci qui la descrizione dell'immagine

Oppure, puoi anche tracciare triangoli superiore / inferiore sinistro / destro di matrici quadrate, ad esempio una matrice di correlazione che è quadrata ed è simmetrica, quindi la rappresentazione di tutti i valori sarebbe comunque ridondante.

corr = np.corrcoef(np.random.randn(10, 200))
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
with sns.axes_style("white"):
    ax = sns.heatmap(corr, mask=mask, vmax=.3, square=True,  cmap="YlGnBu")
    plt.show()

inserisci qui la descrizione dell'immagine


1
Sono molto affezionato al tipo di trama e la mezza matrice è utile. Due domande: 1) nella prima trama i quadratini sono separati da linee bianche, potrebbero essere uniti? 2) la larghezza della linea bianca sembra variare, è un artefatto?
P. Camilleri,

1
Puoi usare l'argomento 'linewidth' che ho usato nella prima trama per qualsiasi altra trama (nella seconda trama per esempio), per ottenere quadrati distanziati. Le larghezze delle linee sembrano variare solo nella prima trama a causa di problemi di schermate, in realtà non variano nella realtà, dovrebbero rimanere alla costante che le hai impostate.
PyRsquared il

mentre questo è vero - non penso che una risposta usando Seaborn dovrebbe essere considerata piena per una domanda che afferma specificamente matplotlib.
baxx

28

Per un numpyarray 2d , utilizzare semplicemente imshow()può aiutarti:

import matplotlib.pyplot as plt
import numpy as np


def heatmap2d(arr: np.ndarray):
    plt.imshow(arr, cmap='viridis')
    plt.colorbar()
    plt.show()


test_array = np.arange(100 * 100).reshape(100, 100)
heatmap2d(test_array)

La mappa di calore del codice di esempio

Questo codice produce una mappa di calore continua.

Puoi scegliere un altro built-in colormapda qui .


18

Vorrei usare la funzione pcolor / pcolormesh di matplotlib poiché consente una spaziatura non uniforme dei dati.

Esempio preso da matplotlib :

import matplotlib.pyplot as plt
import numpy as np

# generate 2 2d grids for the x & y bounds
y, x = np.meshgrid(np.linspace(-3, 3, 100), np.linspace(-3, 3, 100))

z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
# x and y are bounds, so z should be the value *inside* those bounds.
# Therefore, remove the last value from the z array.
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()

fig, ax = plt.subplots()

c = ax.pcolormesh(x, y, z, cmap='RdBu', vmin=z_min, vmax=z_max)
ax.set_title('pcolormesh')
# set the limits of the plot to the limits of the data
ax.axis([x.min(), x.max(), y.min(), y.max()])
fig.colorbar(c, ax=ax)

plt.show()

output del grafico pcolormesh


12

Ecco come farlo da un CSV:

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata

# Load data from CSV
dat = np.genfromtxt('dat.xyz', delimiter=' ',skip_header=0)
X_dat = dat[:,0]
Y_dat = dat[:,1]
Z_dat = dat[:,2]

# Convert from pandas dataframes to numpy arrays
X, Y, Z, = np.array([]), np.array([]), np.array([])
for i in range(len(X_dat)):
        X = np.append(X, X_dat[i])
        Y = np.append(Y, Y_dat[i])
        Z = np.append(Z, Z_dat[i])

# create x-y points to be used in heatmap
xi = np.linspace(X.min(), X.max(), 1000)
yi = np.linspace(Y.min(), Y.max(), 1000)

# Z is a matrix of x-y values
zi = griddata((X, Y), Z, (xi[None,:], yi[:,None]), method='cubic')

# I control the range of my colorbar by removing data 
# outside of my range of interest
zmin = 3
zmax = 12
zi[(zi<zmin) | (zi>zmax)] = None

# Create the contour plot
CS = plt.contourf(xi, yi, zi, 15, cmap=plt.cm.rainbow,
                  vmax=zmax, vmin=zmin)
plt.colorbar()  
plt.show()

dov'è dat.xyznella forma

x1 y1 z1
x2 y2 z2
...

1
Solo un breve avvertimento: ho dovuto cambiare il metodo da cubico a più vicino o lineare perché il cubo ha provocato molti NaN poiché sto lavorando con valori piuttosto piccoli tra 0..1
Maikefer
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.