Zeichnen einer 2D-Heatmap mit Matplotlib

139

Mit Matplotlib möchte ich eine 2D-Heatmap zeichnen. Meine Daten sind ein n-mal-n-Numpy-Array mit einem Wert zwischen 0 und 1. Für das (i, j) -Element dieses Arrays möchte ich ein Quadrat an der (i, j) -Koordinate in my zeichnen Heatmap, deren Farbe proportional zum Wert des Elements im Array ist.

Wie kann ich das machen?

Karnivaurus
quelle
2
Hast du dir die matplotlibGalerie vor dem Posten überhaupt angesehen? Es gibt einige gute Beispiele, die verwenden imshow, pcolorund pcolormeshdie tun, was Sie wollen
tmdavison
Mögliches Duplikat des mehrfarbigen Heat Map-Fehlers Python
jkalden

Antworten:

187

Die imshow()Funktion mit Parametern interpolation='nearest'und cmap='hot'sollte machen was Sie wollen.

import matplotlib.pyplot as plt
import numpy as np

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

Geben Sie hier die Bildbeschreibung ein

P. Camilleri
quelle
1
Ich denke nicht, dass es notwendig ist, Interpolation anzugeben.
miguel.martin
2
@ miguel.martin gemäß pyplot's doc: "Wenn die Interpolation None ist (ihr Standardwert), ist standardmäßig rc image.interpolation". Ich denke, es ist notwendig, es aufzunehmen.
P. Camilleri
@ P.Camilleri Wie skaliere ich die X- und Y-Achse? (Nur die Zahlen ändern, kein Zoom).
Dole
63

Seaborn erledigt einen Großteil der manuellen Arbeit und zeichnet automatisch einen Farbverlauf an der Seite des Diagramms usw.

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

Geben Sie hier die Bildbeschreibung ein

Oder Sie können sogar obere / untere linke / rechte Dreiecke von quadratischen Matrizen zeichnen, z. B. eine Korrelationsmatrix, die quadratisch und symmetrisch ist, sodass das Zeichnen aller Werte ohnehin redundant wäre.

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

Geben Sie hier die Bildbeschreibung ein

PyRsquared
quelle
1
Ich mag den Handlungstyp sehr und die Halbmatrix ist nützlich. Zwei Fragen: 1) In der ersten Darstellung sind die kleinen Quadrate durch weiße Linien getrennt. Könnten sie verbunden sein? 2) Die Breite der weißen Linie scheint zu variieren. Ist dies ein Artefakt?
P. Camilleri
1
Sie können das Argument 'Linienbreite', das ich im ersten Diagramm verwendet habe, für jedes andere Diagramm (z. B. im zweiten Diagramm) verwenden, um Quadrate mit Abstand zu erhalten. Die Linienbreiten scheinen nur im ersten Diagramm aufgrund von Screenshot-Problemen zu variieren. Sie variieren in der Realität nicht. Sie sollten auf der Konstante bleiben, die Sie festgelegt haben.
PyRsquared
Dies ist zwar wahr - ich denke nicht, dass eine Antwort mit Seaborn als vollständig für eine Frage angesehen werden sollte, die speziell Matplotlib angibt.
Baxx
28

Für ein 2D- numpyArray kann die einfache Verwendung imshow()hilfreich sein:

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)

Die Heatmap des Beispielcodes

Dieser Code erstellt eine kontinuierliche Heatmap.

Sie können eine andere in integrierten wählen colormapvon hier .

huangbiubiu
quelle
18

Ich würde die pcolor / pcolormesh- Funktion von matplotlib verwenden, da sie einen ungleichmäßigen Abstand der Daten ermöglicht.

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

pcolormesh-Plotausgabe

Erasmus Cedernaes
quelle
12

So geht's mit einer 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()

wo dat.xyzist in der Form

x1 y1 z1
x2 y2 z2
...
Kilojoule
quelle
1
Nur ein kurzer Hinweis: Ich musste die Methode von kubisch auf entweder am nächsten oder linear ändern, da die kubische Methode zu vielen NaNs führte, da ich mit eher kleinen Werten zwischen 0..1
Maikefer