2010-11-08 32 views
7

J'essaie d'utiliser the scipy.stats.gaussian_kde class pour lisser certaines données discrètes collectées avec les informations de latitude et de longitude, de sorte qu'il apparaît comme quelque peu similaire à une carte de contour à la fin, où le les densités élevées sont les pics et les faibles densités sont la vallée.Utilisation de scipy.stats.gaussian_kde avec des données bidimensionnelles

J'ai du mal à mettre un jeu de données en deux dimensions dans la classe gaussian_kde. J'ai joué autour de comprendre comment il fonctionne avec 1 données dimensionnelles, donc je pensais que 2 dimensions serait quelque chose le long des lignes de:

from scipy import stats 
from numpy import array 
data = array([[1.1, 1.1], 
       [1.2, 1.2], 
       [1.3, 1.3]]) 
kde = stats.gaussian_kde(data) 
kde.evaluate([1,2,3],[1,2,3]) 

qui dit que j'ai 3 points à [1.1, 1.1], [1.2, 1.2], [1.3, 1.3]. et je veux avoir l'estimation de densité de noyau en utilisant de 1 à 3 en utilisant la largeur de 1 sur l'axe x et y.

Lors de la création du gaussian_kde, il ne cesse de me donner cette erreur:

raise LinAlgError("singular matrix") 
numpy.linalg.linalg.LinAlgError: singular matrix 

En regardant dans le code source de gaussian_kde, je me rends compte que la façon dont je pense à ce que signifie ensemble de données est complètement différent de la façon dont la la dimensionnalité est calculée, mais je n'ai trouvé aucun exemple de code montrant comment les données multidimensionnelles fonctionnent avec le module. Quelqu'un pourrait-il m'aider avec quelques exemples de façons d'utiliser gaussian_kde avec des données multidimensionnelles?

+0

Essayez-le avec des données qui ne sont pas toutes dans une ligne. Je ne suis pas sûr si cela devrait échouer pour cela, ou si c'est un bug. – endolith

Répondre

4

Je pense que vous mélangez l'estimation de la densité du noyau avec l'interpolation ou peut-être la régression du noyau. KDE estime la distribution des points si vous avez un plus grand nombre de points. Je ne suis pas sûr de l'interpolation que vous voulez, mais les splines ou rbf dans scipy.interpolate seront plus appropriés.

Si vous voulez une régression de noyau unidimensionnelle, alors vous pouvez trouver une version dans scikits.statsmodels avec plusieurs noyaux différents.

mise à jour: voici un exemple (si c'est ce que vous voulez)

>>> data = 2 + 2*np.random.randn(2, 100) 
>>> kde = stats.gaussian_kde(data) 
>>> kde.evaluate(np.array([[1,2,3],[1,2,3]])) 
array([ 0.02573917, 0.02470436, 0.03084282]) 

gaussian_kde a des variables dans les lignes et les observations dans les colonnes, donc renversées l'orientation de l'habituel dans les statistiques. Dans votre exemple, les trois points sont sur une ligne, donc il y a une corrélation parfaite. C'est, je suppose, la raison de la matrice singulière.

Réglage de l'orientation du tableau et en ajoutant un petit bruit, l'exemple fonctionne, mais il semble encore très concentré, par exemple, vous n'avez pas un point quelconque de l'échantillon près (3,3):

>>> data = np.array([[1.1, 1.1], 
       [1.2, 1.2], 
       [1.3, 1.3]]).T 
>>> data = data + 0.01*np.random.randn(2,3) 
>>> kde = stats.gaussian_kde(data) 
>>> kde.evaluate(np.array([[1,2,3],[1,2,3]])) 
array([ 7.70204299e+000, 1.96813149e-044, 1.45796523e-251]) 
+0

Je ne suis pas un statisticien, mais ma lecture de la régression de KDE et du noyau et de la mention «contour map» de jet me donne à penser que KDE est ce que l'on veut dire. – endolith

5

This example semble être ce que vous cherchez:

import numpy as np 
import scipy.stats as stats 
from matplotlib.pyplot import imshow 

# Create some dummy data 
rvs = np.append(stats.norm.rvs(loc=2,scale=1,size=(2000,1)), 
       stats.norm.rvs(loc=0,scale=3,size=(2000,1)), 
       axis=1) 

kde = stats.kde.gaussian_kde(rvs.T) 

# Regular grid to evaluate kde upon 
x_flat = np.r_[rvs[:,0].min():rvs[:,0].max():128j] 
y_flat = np.r_[rvs[:,1].min():rvs[:,1].max():128j] 
x,y = np.meshgrid(x_flat,y_flat) 
grid_coords = np.append(x.reshape(-1,1),y.reshape(-1,1),axis=1) 

z = kde(grid_coords.T) 
z = z.reshape(128,128) 

imshow(z,aspect=x_flat.ptp()/y_flat.ptp()) 

enter image description here

Haches besoin de fixation, de toute évidence.

Vous pouvez également faire un diagramme de dispersion des données avec

scatter(rvs[:,0],rvs[:,1]) 

enter image description here

+0

https://gist.github.com/1035069 et http://flic.kr/p/9V6onm par exemple – endolith

+0

quand vous dites, l'axe a besoin de fixer, que voulez-vous dire? Parce que je fais la même chose avec des données et pour une raison quelconque, il redonne un peu d'excès en dessous et au-dessus de la min et max des données – ThePredator

+0

@Srivatsan: Je pense que je voulais juste dire qu'il devrait avoir un format plus carré – endolith

0

L'exemple affiché dans la partie supérieure réponse ne fonctionne pas pour moi.J'ai dû le modifier un petit peu et cela fonctionne maintenant:

import numpy as np 
import scipy.stats as stats 
from matplotlib import pyplot as plt 

# Create some dummy data 
rvs = np.append(stats.norm.rvs(loc=2,scale=1,size=(2000,1)), 
       stats.norm.rvs(loc=0,scale=3,size=(2000,1)), 
       axis=1) 

kde = stats.kde.gaussian_kde(rvs.T) 

# Regular grid to evaluate kde upon 
x_flat = np.r_[rvs[:,0].min():rvs[:,0].max():128j] 
y_flat = np.r_[rvs[:,1].min():rvs[:,1].max():128j] 
x,y = np.meshgrid(x_flat,y_flat) 
grid_coords = np.append(x.reshape(-1,1),y.reshape(-1,1),axis=1) 

z = kde(grid_coords.T) 
z = z.reshape(128,128) 

plt.imshow(z,aspect=x_flat.ptp()/y_flat.ptp()) 
plt.show()