Wykreślanie mapy cieplnej 2D za pomocą Matplotlib

148

Korzystając z Matplotlib, chcę wykreślić mapę cieplną 2D. Moje dane to tablica Numpy n-by-n, każda o wartości od 0 do 1. Tak więc dla elementu (i, j) tej tablicy chcę wykreślić kwadrat o współrzędnej (i, j) w moim mapa cieplna, której kolor jest proporcjonalny do wartości elementu w tablicy.

Jak mogę to zrobić?

Karnivaurus
źródło
2
czy w ogóle obejrzałeś matplotlibgalerię przed wysłaniem? Istnieje kilka przykładów dobrych użyciem imshow, pcolori pcolormeshże to, co chcesz
tmdavison

Odpowiedzi:

197

imshow()Funkcja z parametrami interpolation='nearest'i cmap='hot'powinien robić to, co chcesz.

import matplotlib.pyplot as plt
import numpy as np

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

wprowadź opis obrazu tutaj

P. Camilleri
źródło
1
Nie sądzę, by konieczne było określenie interpolacji.
miguel.martin
2
@ miguel.martin zgodnie z dokumentem pyplot: "Jeśli interpolacja jest ustawiona na Brak (wartość domyślna), domyślnie rc image.interpolation". Więc myślę, że to konieczne.
P. Camilleri
@ P.Camilleri Jak wyskalować osie X i Y? (Zmień tylko liczby, bez powiększenia).
Dole
70

Seaborn wykonuje wiele ręcznych prac i automatycznie kreśli gradient z boku wykresu itp.

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

wprowadź opis obrazu tutaj

Lub możesz nawet wykreślić górny / dolny lewy / prawy trójkąt macierzy kwadratowych, na przykład macierz korelacji, która jest kwadratowa i symetryczna, więc wykreślanie wszystkich wartości i tak byłoby zbędne.

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

wprowadź opis obrazu tutaj

PyRsquared
źródło
1
Bardzo lubię typ fabuły, a pół macierz jest przydatna. Dwa pytania: 1) na pierwszym wykresie małe kwadraty są oddzielone białymi liniami, czy mogą być połączone? 2) szerokość białej linii wydaje się różna, czy to artefakt?
P. Camilleri
1
Możesz użyć argumentu „szerokość linii”, którego użyłem na pierwszym wykresie dla dowolnego innego wykresu (na przykład na drugim wykresie), aby uzyskać rozstawione kwadraty. Wydaje się, że szerokości linii zmieniają się tylko na pierwszym wykresie z powodu problemów ze zrzutami ekranu, w rzeczywistości nie różnią się one, powinny pozostać na stałym poziomie, który je ustawiłeś.
PyRsquared
Chociaż to prawda - nie sądzę, aby odpowiedź wykorzystująca labraksa powinna być uważana za pełną w przypadku pytania, które zawiera konkretną informację o matplotlib.
baxx
28

W przypadku numpytablicy 2d po prostu użyj imshow()może pomóc:

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)

Mapa cieplna przykładowego kodu

Ten kod tworzy ciągłą mapę cieplną.

Można wybrać inny wbudowaną colormapod tutaj .

huangbiubiu
źródło
23

Chciałbym użyć matplotlib za pcolor / pcolormesh funkcję, ponieważ pozwala nierównomiernych odstępach danych.

Przykład zaczerpnięty z 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()

Wyjście wykresu pcolormesh

Erasmus Cedernaes
źródło
13

Oto jak to zrobić z pliku 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()

gdzie dat.xyzjest w formularzu

x1 y1 z1
x2 y2 z2
...
kilodżule
źródło
1
Tylko krótka uwaga: musiałem zmienić metodę z sześciennej na najbliższą lub liniową, ponieważ sześcienna dała dużo NaN, ponieważ pracuję z raczej małymi wartościami między 0..1
Maikefer