Filtrado de coordenadas en función de la distancia desde un punto.

Tengo dos matrices decir:

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

Me gustaría encontrar todos los valores de A que no estén dentro de un radio de 2 desde B

Mi respuesta debe ser:

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

¿Hay una forma pythonica de hacer esto?

Lo que he intentado es:

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

Pero me di cuenta de que np.extract aplana A y no consigo lo que se espera.

Sea R el radio aquí. Tendríamos pocos métodos para resolverlo, como veremos a continuación.

Enfoque # 1: Uso de cdist

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

Enfoque # 2: Usar np.einsum

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

Enfoque # 3: Usar np.linalg.norm

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

Enfoque # 4: Uso matrix-multiplication de np.dot con np.dot

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

Enfoque # 5: Uso de una combinación de einsum y matrix-multiplication

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

Enfoque # 6: Uso de la broadcasting

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

Por lo tanto, para obtener los puntos dentro del radio R simplemente reemplace > con < en las soluciones mencionadas anteriormente.

Otro enfoque útil no mencionado por @Divakar es usar un 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] 

El beneficio principal es que será mucho más rápido que cualquier enfoque directo a medida que aumente el tamaño de la matriz, ya que la estructura de datos evita calcular una distancia para cada punto en A