根据距离点的距离过滤坐标

时间:2017-12-11 15:02:52

标签: python numpy scipy

我有两个阵列说:

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])

我希望A找到B的所有值,这些值不在C = [[3,4,1.2],[4,3,2.33],[6,5,0.3],[4,5,1.2],[5,5,1.5]] 的半径范围内。

我的回答应该是:

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

有没有pythonic的方法来做到这一点?

我试过的是:

np.extract

但是我意识到A会使{{1}}变平,而我却得不到我的期望。

2 个答案:

答案 0 :(得分:4)

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:matrix-multiplicationnp.dot一起使用 -

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]

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

答案 1 :(得分:3)

@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中每个点的距离。