根据距点的距离过滤坐标



我有两个数组说:

A = np.array([[ 1.  ,  1.  ,  0.5 ],
              [ 2.  ,  2.  ,  0.7 ],
              [ 3.  ,  4.  ,  1.2 ],
              [ 4.  ,  3.  ,  2.33],
              [ 1.  ,  2.  ,  0.5 ],
              [ 6.  ,  5.  ,  0.3 ],
              [ 4.  ,  5.  ,  1.2 ],
              [ 5.  ,  5.  ,  1.5 ]])
B = np.array([2,1])

我想找到所有不在B的半径2。

A的值。

我的答案应该是:

C = [[3,4,1.2],[4,3,2.33],[6,5,0.3],[4,5,1.2],[5,5,1.5]]

是否有一种pythonic做到这一点?

我尝试的是:

radius = 2
C.append(np.extract((cdist(A[:, :2], B[np.newaxis]) > radius), A))

,但我意识到np.extract扁平A,我没有得到我的预期。

R成为此处的半径。正如接下来讨论的那样,我们将有很少的方法解决。

方法#1:使用cdist-

from scipy.spatial.distance import cdist
A[(cdist(A[:,:2],B[None]) > R).ravel()]

方法#2:使用np.einsum-

d = A[:,:2] - B
out = A[np.einsum('ij,ij->i', d,d) > R**2]

方法#3:使用np.linalg.norm-

A[np.linalg.norm(A[:,:2] - B, axis=1) > R]

方法#4:np.dot一起使用matrix-multiplication-

A[(A[:,:2]**2).sum(1) + (B**2).sum() - 2*A[:,:2].dot(B) > R**2]

方法#5:使用einsummatrix-multiplication的组合 -

A[np.einsum('ij,ij->i',A[:,:2],A[:,:2]) + B.dot(B) - 2*A[:,:2].dot(B) > R**2]

方法#6:使用broadcasting-

A[((A[:,:2] - B)**2).sum(1) > R**2]

因此,要在Radius R中获得点,只需将>替换为上述解决方案中的<

@divakar未提及的另一种有用的方法是使用ckdtree:

from scipy.spatial import cKDTree
# Find indices of points within radius
radius = 2
indices = cKDTree(A[:, :2]).query_ball_point(B, radius)
# Construct a mask over these points
mask = np.zeros(len(A), dtype=bool)
mask[indices] = True
# Extract values not among the nearest neighbors
A[~mask]

主要的好处是,随着数组的大小增加,它将比任何直接方法要快得多,因为数据结构避免了A中每个点的距离。

最新更新