У меня есть неправильная (непрямоугольная) сетка долгота/широта и набор точек в координатах долгота/широта, которые должны соответствовать точкам на сетке (хотя они могут немного отличаться по числовым причинам). Теперь мне нужны индексы соответствующих точек долготы/широты.
Я написал функцию, которая делает это, но она ДЕЙСТВИТЕЛЬНО медленная.
def find_indices(lon,lat,x,y):
lonlat = np.dstack([lon,lat])
delta = np.abs(lonlat-[x,y])
ij_1d = np.linalg.norm(delta,axis=2).argmin()
i,j = np.unravel_index(ij_1d,lon.shape)
return i,j
ind = [find_indices(lon,lat,p*) for p in points]
Я почти уверен, что в numpy/scipy есть лучшее (и более быстрое) решение. Я уже довольно много гуглил, но ответ до сих пор ускользал от меня.
Есть предложения по эффективному поиску индексов соответствующих (ближайших) точек?
PS: этот вопрос возник из другого (нажмите).
Изменить: Решение
Основываясь на ответе @Cong Ma, я нашел следующее решение:
def find_indices(points,lon,lat,tree=None):
if tree is None:
lon,lat = lon.T,lat.T
lonlat = np.column_stack((lon.ravel(),lat.ravel()))
tree = sp.spatial.cKDTree(lonlat)
dist,idx = tree.query(points,k=1)
ind = np.column_stack(np.unravel_index(idx,lon.shape))
return [(i,j) for i,j in ind]
Чтобы представить это решение, а также решение из ответа Дивакара, вот некоторые тайминги функции, в которой я использую find_indices (и где это узкое место с точки зрения скорости) (см. ссылку выше):
spatial_contour_frequency/pil0 : 331.9553
spatial_contour_frequency/pil1 : 104.5771
spatial_contour_frequency/pil2 : 2.3629
spatial_contour_frequency/pil3 : 0.3287
pil0
— мой первоначальный подход, pil1
— Divakar, а pil2
/pil3
— окончательное решение выше, где дерево создается «на лету» в pil2
(т. е. для каждой итерации цикла, в котором вызывается find_indices
) и только один раз в pil3
( подробности в другой теме). Несмотря на то, что усовершенствование Divakar моего первоначального подхода дает мне 3-кратное ускорение, cKDTree выводит это на совершенно новый уровень с еще 50-кратным ускорением! А перенос создания дерева из функции делает работу еще быстрее.
find_indices
. Если ваша сетка фиксирована между вызовами, вы тратите время на построение одного и того же дерева снова и снова. На самом деле построение этого дерева является самым медленным вызовом этой функции. - person Cong Ma   schedule 05.10.2015