Tracer une carte thermique 2D avec Matplotlib


139

En utilisant Matplotlib, je souhaite tracer une carte thermique 2D. Mes données sont un tableau Numpy n-par-n, chacun avec une valeur comprise entre 0 et 1. Donc, pour l'élément (i, j) de ce tableau, je veux tracer un carré à la coordonnée (i, j) dans mon heat map, dont la couleur est proportionnelle à la valeur de l'élément dans le tableau.

Comment puis-je faire ceci?


2
avez-vous regardé la matplotlibgalerie avant de poster? Il existe de bons exemples d'utilisation imshow, pcoloret pcolormeshqui font ce que vous voulez
tmdavison

Réponses:


189

La imshow()fonction avec des paramètres interpolation='nearest'et cmap='hot'devrait faire ce que vous voulez.

import matplotlib.pyplot as plt
import numpy as np

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

entrez la description de l'image ici


1
Je ne pense pas qu'il soit nécessaire de spécifier une interpolation.
miguel.martin

2
@ miguel.martin selon la doc de pyplot: "Si l'interpolation est None (sa valeur par défaut), par défaut rc image.interpolation". Je pense donc qu'il est nécessaire de l'inclure.
P. Camilleri

@ P.Camilleri Comment mettre à l'échelle les axes X et Y? (Changez uniquement les chiffres, pas de zoom).
Dole

64

Seaborn s'occupe d'une grande partie du travail manuel et trace automatiquement un gradient sur le côté du graphique, etc.

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

entrez la description de l'image ici

Ou, vous pouvez même tracer des triangles supérieur / inférieur gauche / droit de matrices carrées, par exemple une matrice de corrélation carrée et symétrique, de sorte que le traçage de toutes les valeurs serait de toute façon redondant.

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

entrez la description de l'image ici


1
J'aime beaucoup le type de tracé et la demi-matrice est utile. Deux questions: 1) dans le premier graphique, les petits carrés sont séparés par des lignes blanches, pourraient-ils être joints? 2) la largeur de la ligne blanche semble varier, est-ce un artefact?
P. Camilleri

1
Vous pouvez utiliser l'argument «linewidth» que j'ai utilisé dans le premier tracé pour n'importe quel autre tracé (dans le deuxième tracé par exemple), pour obtenir des carrés espacés. Les largeurs de ligne ne semblent varier que dans le premier tracé en raison de problèmes de capture d'écran, elles ne varient pas en réalité, elles devraient rester à la constante que vous les avez définie.
PyRsquared

bien que cela soit vrai - je ne pense pas qu'une réponse utilisant seaborn devrait être considérée comme complète pour une question qui énonce spécifiquement matplotlib.
baxx

28

Pour un numpytableau 2d , utilisez simplement imshow()peut vous aider:

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 carte thermique de l'exemple de code

Ce code produit une carte thermique continue.

Vous pouvez choisir un autre intégré à colormappartir d' ici .


18

J'utiliserais la fonction pcolor / pcolormesh de matplotlib car elle permet un espacement non uniforme des données.

Exemple tiré de 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()

sortie du tracé pcolormesh


12

Voici comment le faire à partir d'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()

dat.xyzest dans le formulaire

x1 y1 z1
x2 y2 z2
...

1
Juste un petit avertissement: j'ai dû changer la méthode de cubique à plus proche ou linéaire parce que la cubique entraînait beaucoup de NaN puisque je travaille avec des valeurs plutôt petites entre 0..1
Maikefer
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.