내부가 아닌 두 개의 다른 Numpy 어레이에서 점 사이의 최소 유클리드 거리

StackOverflow https://stackoverflow.com/questions/1871536

문제

나는 두 개의 배열이 있습니다 엑스-와이 좌표, 그리고 나는 사이의 최소 유클리드 거리를 찾고 싶습니다. 하나의 배열을 가리키십시오 모두 다른 배열의 포인트. 배열이 반드시 같은 크기는 아닙니다. 예를 들어:

xy1=numpy.array(
[[  243,  3173],
[  525,  2997]])

xy2=numpy.array(
[[ 682, 2644],
[ 277, 2651],
[ 396, 2640]])

내 현재 메소드는 각 좌표를 통해 반복됩니다 xy 안에 xy1 그리고 그 좌표와 다른 좌표 사이의 거리를 계산합니다.

mindist=numpy.zeros(len(xy1))
minid=numpy.zeros(len(xy1))

for i,xy in enumerate(xy1):
    dists=numpy.sqrt(numpy.sum((xy-xy2)**2,axis=1))
    mindist[i],minid[i]=dists.min(),dists.argmin()

for 루프를 제거하고 두 배열 사이에 요소 단축 계산을 수행하는 방법이 있습니까? 각 행이나 열에서 최소 요소를 찾을 수있는 거리 매트릭스를 생성하는 것을 상상합니다.

문제를 보는 또 다른 방법. 내가 연결한다고 말합니다 xy1 (길이 ) 그리고 xy2 (길이 ) 안으로 xy (길이 N), 그리고 원래 배열의 길이를 저장합니다. 이론적으로 나는 NXN 내가 잡을 수있는 좌표의 거리 매트릭스 MXP 하위 매트릭스. 이 하위 매트릭스를 효율적으로 생성하는 방법이 있습니까?

도움이 되었습니까?

해결책

(몇달 뒤)scipy.spatial.distance.cdist( X, Y )x와 y 2 dim, 3 dim ...에 대한 모든 거리 쌍을 제공합니다.
또한 22 가지 규범을 자세히 수행합니다여기 .

# cdist example: (nx,dim) (ny,dim) -> (nx,ny)

from __future__ import division
import sys
import numpy as np
from scipy.spatial.distance import cdist

#...............................................................................
dim = 10
nx = 1000
ny = 100
metric = "euclidean"
seed = 1

    # change these params in sh or ipython: run this.py dim=3 ...
for arg in sys.argv[1:]:
    exec( arg )
np.random.seed(seed)
np.set_printoptions( 2, threshold=100, edgeitems=10, suppress=True )

title = "%s  dim %d  nx %d  ny %d  metric %s" % (
        __file__, dim, nx, ny, metric )
print "\n", title

#...............................................................................
X = np.random.uniform( 0, 1, size=(nx,dim) )
Y = np.random.uniform( 0, 1, size=(ny,dim) )
dist = cdist( X, Y, metric=metric )  # -> (nx, ny) distances
#...............................................................................

print "scipy.spatial.distance.cdist: X %s Y %s -> %s" % (
        X.shape, Y.shape, dist.shape )
print "dist average %.3g +- %.2g" % (dist.mean(), dist.std())
print "check: dist[0,3] %.3g == cdist( [X[0]], [Y[3]] ) %.3g" % (
        dist[0,3], cdist( [X[0]], [Y[3]] ))


# (trivia: how do pairwise distances between uniform-random points in the unit cube
# depend on the metric ? With the right scaling, not much at all:
# L1 / dim      ~ .33 +- .2/sqrt dim
# L2 / sqrt dim ~ .4 +- .2/sqrt dim
# Lmax / 2      ~ .4 +- .2/sqrt dim

다른 팁

거리의 p 매트릭스에 의해 m을 계산하려면 다음이 작동해야합니다.

>>> def distances(xy1, xy2):
...   d0 = numpy.subtract.outer(xy1[:,0], xy2[:,0])
...   d1 = numpy.subtract.outer(xy1[:,1], xy2[:,1])
...   return numpy.hypot(d0, d1)

그만큼 .outer 전화는 두 축을 따라 두 개의 행렬을 만듭니다. .hypot 전화는 그것들을 같은 모양의 매트릭스 (스칼라 유클리드 거리의)로 바꿉니다.

당신이하려는 일을 위해 :

dists = numpy.sqrt((xy1[:, 0, numpy.newaxis] - xy2[:, 0])**2 + (xy1[:, 1, numpy.newaxis - xy2[:, 1])**2)
mindist = numpy.min(dists, axis=1)
minid = numpy.argmin(dists, axis=1)

편집하다: 전화하는 대신 sqrt, 사각형 등을 사용하면 사용할 수 있습니다 numpy.hypot:

dists = numpy.hypot(xy1[:, 0, numpy.newaxis]-xy2[:, 0], xy1[:, 1, numpy.newaxis]-xy2[:, 1])

허용 된 답변은 질문을 완전히 다루지 않습니다. 최저한의 두 지점 세트 사이의 거리는 사이의 거리가 아닙니다. 모든 두 세트를 가리 킵니다.

원래 질문에 대한 간단한 솔루션은 실제로 사이의 거리를 계산하는 것으로 구성됩니다. 모든 쌍과 엄청나게 최소를 찾는 것은 최저한의 거리. 후자의 문제에 대한 훨씬 빠른 해결책이 존재합니다.

제안 된 모든 솔루션에는 다음과 같은 규모의 실행 시간이 있습니다. m*p = len(xy1)*len(xy2). 이것은 소규모 데이터 세트에 적합하지만 스케일을 다음과 같은 최적의 솔루션을 작성할 수 있습니다. m*log(p), 큰 비용으로 막대한 절약을 생산합니다 xy2 데이터 세트.

이 최적의 실행 시간 스케일링을 사용하여 달성 할 수 있습니다 scipy.spatial.ckdtree 다음과 같이

import numpy as np
from scipy import spatial

xy1 = np.array(
    [[243,  3173],
     [525,  2997]])

xy2 = np.array(
    [[682, 2644],
     [277, 2651],
     [396, 2640]])

# This solution is optimal when xy2 is very large
tree = spatial.cKDTree(xy2)
mindist, minid = tree.query(xy1)
print(mindist)

# This solution by @denis is OK for small xy2
mindist = np.min(spatial.distance.cdist(xy1, xy2), axis=1)
print(mindist)

어디 mindist 각 지점 사이의 최소 거리입니다 xy1 그리고 포인트 세트 xy2

import numpy as np
P = np.add.outer(np.sum(xy1**2, axis=1), np.sum(xy2**2, axis=1))
N = np.dot(xy1, xy2.T)
dists = np.sqrt(P - 2*N)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top