Indice de recherche du point le plus proche dans les tableaux numpy des coordonnées x et y
j'ai deux tableaux numpy 2d: x_array contient des informations de position dans la direction x, y_array contient des positions dans la direction Y.
j'ai alors une longue liste de x,y des points.
pour chaque point de la liste, je dois trouver l'index du tableau de l'emplacement (spécifié dans les tableaux) qui est le plus proche de ce point.
j'ai naïvement produit quelque code qui fonctionne, basé sur cette question: trouver valeur la plus proche dans le tableau de numpy
c'est à dire
import time
import numpy
def find_index_of_nearest_xy(y_array, x_array, y_point, x_point):
distance = (y_array-y_point)**2 + (x_array-x_point)**2
idy,idx = numpy.where(distance==distance.min())
return idy[0],idx[0]
def do_all(y_array, x_array, points):
store = []
for i in xrange(points.shape[1]):
store.append(find_index_of_nearest_xy(y_array,x_array,points[0,i],points[1,i]))
return store
# Create some dummy data
y_array = numpy.random.random(10000).reshape(100,100)
x_array = numpy.random.random(10000).reshape(100,100)
points = numpy.random.random(10000).reshape(2,5000)
# Time how long it takes to run
start = time.time()
results = do_all(y_array, x_array, points)
end = time.time()
print 'Completed in: ',end-start
je fais cela sur un ensemble de données volumineux et voudrais vraiment d'accélérer un peu. Quelqu'un peut-il l'optimiser?
Merci.
mise à JOUR: SOLUTION suggestions suivantes par @silvado et @justin (ci-dessous)
# Shoe-horn existing data for entry into KDTree routines
combined_x_y_arrays = numpy.dstack([y_array.ravel(),x_array.ravel()])[0]
points_list = list(points.transpose())
def do_kdtree(combined_x_y_arrays,points):
mytree = scipy.spatial.cKDTree(combined_x_y_arrays)
dist, indexes = mytree.query(points)
return indexes
start = time.time()
results2 = do_kdtree(combined_x_y_arrays,points_list)
end = time.time()
print 'Completed in: ',end-start
ce code ci-dessus accéléré mon code (recherche de 5000 points en 100x100 matrices) de 100 fois. Fait intéressant, en utilisant scipy.spatial.KDTree (au lieu de scipy.spatial.cKDTree) a donné des temps comparables à ma solution naïve, il est donc certainement intéressant d'utiliser la version cKDTree...
3 réponses
scipy.spatial
dispose également d'une mise en œuvre de l'arbre k-d: scipy.spatial.KDTree
.
l'approche consiste généralement à utiliser d'abord les données ponctuelles pour construire un arbre k-D. La complexité de calcul est de l'ordre de N log N, où N est le nombre de points de données. Les requêtes de portée et les recherches de voisinage le plus proche peuvent alors être effectuées avec la complexité de log N. C'est beaucoup plus efficace que de simplement faire du vélo à travers tous les points (complexité N).
ainsi, si vous avez des questions répétées sur la portée ou le plus proche voisin, un arbre k-D est fortement recommandé.
voici un scipy.spatial.KDTree
exemple
In [1]: from scipy import spatial
In [2]: import numpy as np
In [3]: A = np.random.random((10,2))*100
In [4]: A
Out[4]:
array([[ 68.83402637, 38.07632221],
[ 76.84704074, 24.9395109 ],
[ 16.26715795, 98.52763827],
[ 70.99411985, 67.31740151],
[ 71.72452181, 24.13516764],
[ 17.22707611, 20.65425362],
[ 43.85122458, 21.50624882],
[ 76.71987125, 44.95031274],
[ 63.77341073, 78.87417774],
[ 8.45828909, 30.18426696]])
In [5]: pt = [6, 30] # <-- the point to find
In [6]: A[spatial.KDTree(A).query(pt)[1]] # <-- the nearest point
Out[6]: array([ 8.45828909, 30.18426696])
#how it works!
In [7]: distance,index = spatial.KDTree(A).query(pt)
In [8]: distance # <-- The distances to the nearest neighbors
Out[8]: 2.4651855048258393
In [9]: index # <-- The locations of the neighbors
Out[9]: 9
#then
In [10]: A[index]
Out[10]: array([ 8.45828909, 30.18426696])
si vous pouvez masser vos données dans le bon format, une façon rapide d'aller est d'utiliser les méthodes dans scipy.spatial.distance
:
http://docs.scipy.org/doc/scipy/reference/spatial.distance.html
en particulier pdist
et cdist
fournissent des moyens rapides pour calculer les distances par paires.