二つの異なるnumpyのアレイにおけるポイント間の最小ユークリッド距離ではなく、内

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

質問

私は X の二つの配列がある - Y の座標を、そして私は1つのアレイ内ののポイント間の最小ユークリッド距離を見つけたいですの他のアレイ内のすべてののポイント。アレイは、必ずしも同じ大きさではありません。たとえばます:

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ループを排除し、何とか二つの配列間の要素ごとの計算を行う方法はありますか?私はそれぞれの行または列内の最小要素を見つける可能性があるため、距離行列を生成する想像。

もう一つの方法は、問題を見て。私は(長さ N )(長さ M )とxy1 xy2に(長さを P xyを連結し、そしてIは、元の長さを格納すると言います配列。理論的には、私は、私はのm X pをつかむことができ、そこからそれらの座標から N×nのの距離行列を生成することができなければならないの部分行列。効率的にこの部分行列を生成するための方法はありますか?

役に立ちましたか?

解決

(数ヵ月後) scipy.spatial.distance.cdist( X, Y ) 、距離のすべてのペアを与えます XおよびY 2薄暗い、3薄暗いのための...
また、詳細な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コールは(二つの軸に沿ったスカラー差の)は、2つのそのような行列を作る、.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])

受け入れ答えは完全にポイントの2つのセットの間の最小の距離ではなく、2中のすべてのの点との間の距離を見つけるために、要求の質問に、対処していませんセット。

元の質問への直接的な解決策は、実際のすべてのペアとsusequently最小のものを見つけるの間の距離を計算することから成るAltoughつの最小にのみ関心がある場合、

、これは必要ではありませんの距離。はるかに高速ソリューションは、後者の問題のために存在します。

すべての提案されたソリューションは、m*p = len(xy1)*len(xy2)としてスケール走行時間を持っています。大m*log(p)データセットのための巨大な貯蓄を生産、xy2としてスケールつまりこれは、小さなデータセットのためにOKですが、最適解を書き込むことができます。

この最適な実行時間のスケーリングを使用して達成することができる 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)

mindistxy1の各点と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