Générer un heatmap dans MatPlotLib à l'aide d'un éparpillement de l'ensemble de données
J'ai un ensemble de données X,Y des points (environ 10k) qui sont faciles à tracer un diagramme de dispersion mais que je voudrais représenter comme une heatmap.
J'ai regardé à travers les exemples de MatPlotLib et ils semblent tous d'ores et déjà commencer avec heatmap les valeurs des cellules pour générer l'image.
Est là une méthode qui convertit un tas de x,y, tous différents, pour une heatmap (où les zones avec une fréquence plus élevée de x,y serait plus "chaudes")?
- Tout aussi pertinente: méthode Efficace de calcul de la densité de points espacés de manière irrégulière
Vous devez vous connecter pour publier un commentaire.
Si vous ne voulez pas d'hexagones, vous pouvez utiliser numpy est
histogram2d
fonction:Cela fait une 50x50 heatmap. Si vous voulez, par exemple, 512x384, vous pouvez mettre
bins=(512, 384)
dans l'appel àhistogram2d
.Exemple:
axes
exemple, où je peux ajouter un titre, des étiquettes de l'axe, etc. et puis faire de la normalesavefig()
comme je le ferais pour n'importe quel autre typique matplotlib de la parcelle.plt.savefig('filename.png')
travail? Si vous souhaitez obtenir un des axes de l'instance, l'utilisation Matplotlib est une interface orientée objet:fig = plt.figure()
ax = fig.gca()
ax.imshow(...)
fig.savefig(...)
imshow()
est sur la même catégorie de fonctions, commescatter()
. Honnêtement, je ne comprends pas pourquoiimshow()
convertit un tableau 2d de chars dans des blocs de couleur appropriée, tandis que moi, je ne comprends ce quescatter()
est censé faire avec un tel tableau.plt.imshow(heatmap.T, extent=extent, origin = 'lower')
from matplotlib.colors import LogNorm
plt.imshow(heatmap, norm=LogNorm())
plt.colorbar()
Dans Matplotlib lexique, je pense que vous voulez un hexbin de la parcelle.
Si vous n'êtes pas familier avec ce type de tracé, c'est juste un bivariée histogramme dans lequel le plan xy est pavée par une grille d'hexagones.
Donc à partir d'un histogramme, vous pouvez simplement compter le nombre de points de chute dans chaque hexagone, discretiize le tracé de la région comme un ensemble de windows, d'attribuer à chaque point de l'une de ces fenêtres; enfin, la carte de la windows sur un gamme de couleurs, et vous avez un hexbin diagramme.
Bien que moins fréquemment utilisés que par exemple, des cercles ou des carrés, que les hexagones sont un meilleur choix pour la géométrie de la zone de binning conteneur est intuitive:
hexagones ont le plus proche voisin de symétrie (par exemple, le carré des bacs de ne pas,
par exemple, la distance de un point sur un carré de la frontière à un point
à l'intérieur de ce carré n'est pas égale partout dans le monde) et
hexagone est le plus élevé n-polygone qui donne régulier d'avion
pavage (c'est à dire, vous pouvez re-modèle de votre plancher de la cuisine hexagonale en forme de tuiles, car vous n'aurez pas d'espace vide entre les tuiles lorsque vous avez terminé--pas vrai pour tous les autres supérieur à n, n >= 7, polygones).
(Matplotlib utilise le terme hexbin parcelle, afin de faire (autant que je sache) tous les traçage des bibliothèques pour R; je ne sais pas si c'est le terme généralement accepté pour les parcelles de ce type, bien que je soupçonne que c'est possible étant donné que hexbin est court pour hexagonale binning, qui est décrit l'étape essentielle de la préparation des données pour l'affichage.)
gridsize=
paramètre. Je voudrais choisir un tel, de sorte que les hexagones, il suffit de toucher sans qu'elles se chevauchent. J'ai remarqué quegridsize=100
permettrait de produire de petits hexagones, mais comment choisir la bonne valeur?Au lieu d'utiliser des np.hist2d, qui, en général, produit tout à fait laid histogrammes, je voudrais recycler py-sphviewer, un paquet python pour le rendu des particules de simulations à l'aide d'une adaptative lissage par noyau et qui peut être facilement installé par le programme pep (voir page de documentation). Considérons le code suivant, qui est basé sur l'exemple:
qui produit l'image suivante:
Comme vous le voyez, les images ont l'air assez sympa, et nous sommes en mesure d'identifier les différentes sous-structures sur elle. Ces images sont construites à la propagation d'un poids donné, pour chaque point à l'intérieur d'un certain domaine, défini par le lissage de la longueur, qui s'est donnée par la distance de la plus proche nb voisin (j'ai choisi de 16, 32 et 64 pour les exemples). Ainsi, plus la densité habituellement, les régions sont répartis dans de petites régions par rapport à la densité plus faible des régions.
La fonction myplot est juste une fonction très simple que j'ai écrit afin de donner les données x,y à py-sphviewer à faire de la magie.
Si vous utilisez 1.2.x
Edit: Pour une meilleure approximation de Alejandro réponse, voir ci-dessous.
Je sais que c'est une vieille question, mais je voulais ajouter quelque chose à Alejandro anwser: Si vous voulez une belle image lissée sans l'aide de py-sphviewer place, vous pouvez utiliser
np.histogram2d
et appliquer un filtre gaussien (descipy.ndimage.filters
) à la heatmap:Produit:
Le diagramme de dispersion et s=16 tracées sur eachother pour Agape Gal'lo (cliquez pour mieux voir):
Une différence que j'ai remarqué avec mon filtre gaussien approche et Alejandro était que sa méthode montre de structures locales, beaucoup mieux que le mien. J'ai donc mis en place un simple voisin le plus proche de la méthode au niveau du pixel. Cette méthode calcule pour chaque pixel de l'inverse de la somme des distances de l'
n
points les plus proches dans les données. Cette méthode est à un niveau de résolution assez gourmand en ressources et je pense qu'il y a un moyen plus rapide, alors laissez-moi savoir si vous avez des améliorations. De toute façon, voici le code:Résultat:
myplot
fonction, ajoutez lerange
paramètrenp.histogram2d
:np.histogram2d(x, y, bins=bins, range=[[-5, 5], [-3, 4]])
et dans la boucle for définir les coordonnées x et y de la mfr de l'axe:ax.set_xlim([-5, 5])
ax.set_ylim([-3, 4])
. De plus, par défaut,imshow
conserve le ratio d'aspect identique au ratio de vos axes (donc dans mon exemple, un ratio de 10:7), mais si vous voulez qu'il corresponde à votre fenêtre du tracé, ajoutez le paramètreaspect='auto'
àimshow
.Seaborn a maintenant la jointplot fonction qui devrait fonctionner bien ici:
fig = plt.figure(figsize=(12, 12))
, puis obtenir de l'axe actuel avecax=plt.gca()
, puis ajouter l'argumentax=ax
à lajointplot
fonction.et la question initiale a été... comment faire pour convertir de dispersion des valeurs de valeurs de grille, à droite?
histogram2d
ne compter la fréquence par cellule, cependant, si vous avez d'autres données par cellule que juste la fréquence, vous auriez besoin de plus de travail à faire.Donc, j'ai un dataset avec Z-résultats pour les coordonnées X et Y. Cependant, j'ai été le calcul de quelques points à l'extérieur de la zone d'intérêt (grands espaces), et des tas de points dans une petite zone d'intérêt.
Oui ici, il devient plus difficile mais aussi plus amusant. Certaines bibliothèques (désolé):
pyplot est mon moteur graphique d'aujourd'hui,
la cm est une gamme de cartes de couleurs avec quelques initeresting choix.
numpy pour les calculs,
et griddata pour la fixation des valeurs d'une grille fixe.
Le dernier est important, surtout parce que la fréquence de xy des points n'est pas également répartie dans mes données. Tout d'abord, nous allons commencer avec quelques limites montage de mes données et de l'arbitraire de la taille de la grille. Les données d'origine a points de données également en dehors de ces x et y des limites.
Nous avons donc défini une grille avec 500 pixels entre les valeurs min et max de x et y.
Dans mes données, il y a beaucoup plus de 500 valeurs disponibles dans la zone d'un grand intérêt; alors que dans le faible taux d'intérêt de la zone, il y a même pas 200 valeurs dans la grille total; entre les graphiques des limites de
x_min
etx_max
il y a encore moins.Donc, pour obtenir une belle image, la tâche est d'obtenir une moyenne pour l'intérêt supérieur de valeurs et de combler les lacunes d'ailleurs.
Je définir ma grille de maintenant. Pour chaque xx-yy paire, je veux avoir une couleur.
Pourquoi la forme étrange? scipy.griddata veut une forme de (n, D).
Griddata calcule une valeur pour chaque point de la grille, par une méthode prédéfini.
- Je choisir "le plus proche" vide", les points de la grille sera remplie avec les valeurs de la voisine la plus proche. C'est comme si les zones avec moins d'informations ont plus de cellules (même si ce n'est pas le cas). On pourrait choisir pour interpoler "linéaire", puis des zones avec moins d'informations, semble moins forte. Question de goût, vraiment.
Et hop, nous matplotlib pour afficher l'intrigue
Autour de l'pointu partie de la Forme de V, vous voyez j'ai fait beaucoup de calculs lors de mes recherches pour le sweet spot, tandis que la moins intéressante de pièces, presque partout ailleurs, ont une résolution inférieure.
Faire un tableau en 2 dimensions qui correspond aux cellules de votre image finale, appelé à dire
heatmap_cells
et de l'instancier comme tous les zéros.Choisir deux facteurs d'échelle qui définissent la différence entre chaque élément du tableau en unités réelles, pour chaque dimension, disons
x_scale
ety_scale
. Choisir de tels que tous vos points de données va tomber dans les limites de la heatmap tableau.Pour chaque raw datapoint avec
x_value
ety_value
:heatmap_cells[floor(x_value/x_scale),floor(y_value/y_scale)]+=1
Très similaire à @Piti réponse, mais à l'aide de 1 appel, au lieu de 2 pour générer les points:
De sortie:
Je crains que je suis un peu en retard à la fête, mais j'ai eu une question similaire il y a longtemps. La accepté de répondre (par @ptomato) m'a beaucoup aidé, mais j'avais aussi envie de poster ceci dans le cas où il est d'usage à quelqu'un.
Voici le résultat
Voici celui que j'ai fait sur un de 1 Million de points de l'ensemble avec 3 catégories (de couleur Rouge, Vert et Bleu). Voici un lien vers le référentiel si vous souhaitez essayer la fonction. Dépôt Github