我有一个不规则的(非矩形的)lon/lat网格和一堆在lon/lat坐标系中的点,这些点应该与网格上的点相对应(尽管它们可能由于数值原因而稍微偏离),现在我需要对应的lon/lat点的索引。
我已经写了一个函数来做这个,但是它真的很慢。
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:**这个问题来自another one)。
3条答案
按热度按时间mwg9r5ms1#
如果这些点足够局部化,你可以直接尝试
scipy.spatial
的cKDTree
实现,正如我在另一篇文章中所讨论的,那篇文章是关于插值的,但你可以忽略它,只使用查询部分。TL;DR版本:
阅读
scipy.sptial.cKDTree
的文档,通过将(n, m)
形状的numpy
ndarray对象传递给初始化器来创建树,树将从n
m
维坐标创建。然后,使用
tree.query()
检索k
的最近邻居(可能使用近似和并行化,参见文档),或者使用tree.query_ball_point()
查找给定距离容差内的所有邻居。如果这些点没有很好地局部化,并且球面曲率/非平凡拓扑起作用,你可以尝试将流形分成多个部分,每个部分都足够小,可以被认为是局部的。
ttcibm8c2#
这是使用
scipy.spatial.distance.cdist
的通用矢量化方法-样品运行-
运行时间测试-
定义功能:
时间:
为了挤出更多的性能,可以使用
np.concatenate
代替np.column_stack
。j8yoct9x3#
根据@丛马的回答,我找到了以下解决方案:
为了更好地理解这个解决方案以及Divakar's answer中的解决方案,下面是我使用
find_indices
的函数的一些时序(以及它在速度方面的瓶颈):pil0
是我的初始方法,pil1
是Divakar的,pil2
/pil3
是上面的最终解决方案,其中树是在pil2
中动态创建的(即,对于调用find_indices
的循环的每次迭代)并且在pil3
中仅一次(有关详细信息,请参见other thread)尽管Divakar对我最初的方法进行了改进,使速度提高了3倍,cKDTree将这一点提升到了一个全新的水平,又有了50倍的加速!而且将树的创建移出函数使事情变得更快。此答案以edit的形式发布在CC BY-SA 3.0下,通过OP flotzilla有效查找非矩形2D网格上最近点的索引。