我有两个阵列说:
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}}变平,而我却得不到我的期望。
答案 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-multiplication
与np.dot
一起使用 -
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]
因此,要获得半径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
中每个点的距离。