web-dev-qa-db-fra.com

Visualisation des nuages ​​de points avec points de chevauchement dans matplotlib

Je dois représenter environ 30 000 points dans un nuage de points dans matplotlib. Ces points appartiennent à deux classes différentes, donc je veux les représenter avec des couleurs différentes.

J'ai réussi à le faire, mais il y a un problème. Les points se chevauchent dans de nombreuses régions et la classe que je représente pour la dernière sera visualisée au-dessus de l'autre, en la cachant. De plus, avec le nuage de points, il n'est pas possible de montrer combien de points se trouvent dans chaque région. J'ai également essayé de faire un histogramme 2d avec histogram2d et imshow, mais il est difficile de montrer clairement les points appartenant aux deux classes.

Pouvez-vous suggérer un moyen de clarifier à la fois la distribution des classes et la concentration des points?

EDIT: Pour être plus clair, voici le lien vers mon fichier de données au format "x, y, class"

25
papafe

Une approche consiste à tracer les données sous la forme d'un nuage de points avec un alpha faible, afin que vous puissiez voir les points individuels ainsi qu'une mesure approximative de la densité. (L'inconvénient est que l'approche a une plage de chevauchement limitée qu'elle peut montrer - c'est-à-dire une densité maximale d'environ 1/alpha.)

Voici un exemple:

enter image description here

Comme vous pouvez l'imaginer, en raison de la plage limitée de chevauchements qui peut être exprimée, il y a un compromis entre la visibilité des points individuels et l'expression de la quantité de chevauchement (et la taille du marqueur, du tracé, etc.).

import numpy as np
import matplotlib.pyplot as plt

N = 10000
mean = [0, 0]
cov = [[2, 2], [0, 2]]
x,y = np.random.multivariate_normal(mean, cov, N).T

plt.scatter(x, y, s=70, alpha=0.03)
plt.ylim((-5, 5))
plt.xlim((-5, 5))
plt.show()

(Je suppose ici que vous vouliez 30e3 points, pas 30e6. Pour 30e6, je pense qu'un certain type de tracé de densité moyenne serait nécessaire.)

27
tom10

Vous pouvez également colorer les points en calculant d'abord une estimation de la densité du noyau de la distribution de la dispersion et en utilisant les valeurs de densité pour spécifier une couleur pour chaque point de la diffusion. Pour modifier le code dans l'exemple précédent:

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import gaussian_kde as kde
from matplotlib.colors import Normalize
from matplotlib import cm

N = 10000
mean = [0,0]
cov = [[2,2],[0,2]]

samples = np.random.multivariate_normal(mean,cov,N).T
densObj = kde( samples )

def makeColours( vals ):
    colours = np.zeros( (len(vals),3) )
    norm = Normalize( vmin=vals.min(), vmax=vals.max() )

    #Can put any colormap you like here.
    colours = [cm.ScalarMappable( norm=norm, cmap='jet').to_rgba( val ) for val in vals]

    return colours

 colours = makeColours( densObj.evaluate( samples ) )

 plt.scatter( samples[0], samples[1], color=colours )
 plt.show()

Scatter plot with density information

J'ai appris cette astuce il y a quelque temps lorsque j'ai remarqué la documentation de la fonction scatter -

c : color or sequence of color, optional, default : 'b'

c peut être une chaîne de format de couleur unique, ou une séquence de spécifications de couleur de longueur N, ou une séquence de N nombres à mapper aux couleurs à l'aide de cmap et norm spécifiés via kwargs (voir ci-dessous). Notez que c ne doit pas être une seule séquence numérique RVB ou RVBA car il est impossible de la distinguer d'un tableau de valeurs à colorier. c peut être un tableau 2D dans lequel les lignes sont RVB ou RGBA, cependant, y compris le cas d'une seule ligne pour spécifier la même couleur pour tous les points.

25
vishakad