Memfilter koordinat berdasarkan jarak dari suatu titik

Saya memiliki dua array yang mengatakan:

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

Saya ingin mencari semua nilai A yang tidak berada dalam radius 2 dari B.

Jawaban saya seharusnya:

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

Apakah ada cara pythonic untuk melakukan ini?

Apa yang saya coba adalah:

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

Namun saya menyadari bahwa np.extract mendatar A dan saya tidak mendapatkan apa yang diharapkan.


person user3185171    schedule 11.12.2017    source sumber


Jawaban (2)


Misalkan R adalah radiusnya. Kami memiliki beberapa metode untuk menyelesaikannya, seperti yang dibahas selanjutnya.

Pendekatan #1 : Menggunakan cdist -

from scipy.spatial.distance import cdist

A[(cdist(A[:,:2],B[None]) > R).ravel()]

Pendekatan #2 : Menggunakan np.einsum -

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

Pendekatan #3 : Menggunakan np.linalg.norm -

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

Pendekatan #4 : Menggunakan matrix-multiplication dengan np.dot -

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

Pendekatan #5 : Menggunakan kombinasi einsum dan matrix-multiplication -

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

Pendekatan #6 : Menggunakan broadcasting -

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

Oleh karena itu, untuk mendapatkan poin dalam radius R cukup ganti > dengan < pada solusi yang disebutkan di atas.

person Divakar    schedule 11.12.2017

Pendekatan berguna lainnya yang tidak disebutkan oleh @Divakar adalah dengan menggunakan 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]

Keuntungan utamanya adalah pendekatan ini akan jauh lebih cepat dibandingkan pendekatan langsung mana pun seiring bertambahnya ukuran array, karena struktur data menghindari penghitungan jarak untuk setiap titik di A.

person jakevdp    schedule 12.12.2017