Tengo dos matrices numéricas 2d: x_array contiene información posicional en la dirección x, y_array contiene posiciones en la dirección y.
Entonces tengo una larga lista de puntos x, y.
Para cada punto de la lista, necesito encontrar el índice de matriz de la ubicación (especificada en las matrices) que está más cerca de ese punto.
Ingenuamente he producido un código que funciona, basado en esta pregunta: Encuentre el valor más cercano en la matriz numpy
es decir
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
Estoy haciendo esto en un gran conjunto de datos y realmente me gustaría acelerarlo un poco. ¿Alguien puede optimizar esto?
Gracias.
ACTUALIZACIÓN: SOLUCIÓN siguiendo las sugerencias de @silvado y @justin (abajo)
# 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
Este código anterior aceleró mi código (buscando 5000 puntos en matrices de 100x100) 100 veces. Curiosamente, usar scipy.spatial.KDTree (en lugar de scipy.spatial.cKDTree ) dio tiempos comparables a mi solución ingenua, por lo que definitivamente vale la pena usar la versión cKDTree ...