scipy 快速融合numpy-2d(矢量化)中的接近点

kcugc4gi  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(135)

我有一个问题与这里提出的问题相似:simple way of fusing a few close points。我想用坐标的平均值来替换彼此接近的点。单元格中的接近程度由用户指定(我说的是欧几里得距离)。
在我的例子中,我有很多点(大约100万)。这个方法是有效的,但是很耗时,因为它使用了一个双for循环。
有没有更快的方法来检测和融合numpy 2d数组中的接近点?
为了完整起见,我添加了一个示例:

points=array([[  382.49056159,   640.1731949 ],
   [  496.44669161,   655.8583119 ],
   [ 1255.64762859,   672.99699399],
   [ 1070.16520917,   688.33538171],
   [  318.89390168,   718.05989421],
   [  259.7106383 ,   822.2       ],
   [  141.52574427,    28.68594436],
   [ 1061.13573287,    28.7094536 ],
   [  820.57417943,    84.27702407],
   [  806.71416007,   108.50307828]])

点的散点图如下所示。红色圆圈表示点彼此靠近(在本例中,阵列中最后两个点之间的距离为27.91)。因此,如果用户指定最小距离为30,则应融合这些点。

在fuse函数的输出中,最后到点被融合。看起来如下:


# output

array([[  382.49056159,   640.1731949 ],
   [  496.44669161,   655.8583119 ],
   [ 1255.64762859,   672.99699399],
   [ 1070.16520917,   688.33538171],
   [  318.89390168,   718.05989421],
   [  259.7106383 ,   822.2       ],
   [  141.52574427,    28.68594436],
   [ 1061.13573287,    28.7094536 ],
   [  813.64416975,    96.390051175]])
h7appiyu

h7appiyu1#

如果您有大量的点,则使用scipy.spatial.KDTree构建k-D tree可能会更快,然后查询它以查找比某个阈值更近的点对:

import numpy as np
from scipy.spatial import KDTree

tree = KDTree(points)
rows_to_fuse = tree.query_pairs(r=30)    

print(repr(rows_to_fuse))

# {(8, 9)}

print(repr(points[list(rows_to_fuse)]))

# array([[ 820.57417943,   84.27702407],

# [ 806.71416007,  108.50307828]])

这种方法的主要优点是,您不需要计算数据集中每对点之间的距离。

4uqofj5v

4uqofj5v2#

您可以使用scipy的距离函数(例如pdist),以便快速找到应合并的点:

import numpy as np
from scipy.spatial.distance import pdist, squareform

d = squareform(pdist(a))
d = np.ma.array(d, mask=np.isclose(d, 0))
a[d.min(axis=1) < 30]

# array([[ 820.57417943,   84.27702407],

# [ 806.71416007,  108.50307828]])

注意事项
对于大样本,此方法可能会导致内存错误,因为它存储的是包含相对距离的完整矩阵。

相关问题