我有两个数组说:
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:使用einsum
和matrix-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
中每个点的距离。