web-dev-qa-db-ja.com

Pythonのセットから最も近い座標ペアを効率的に見つける

問題

私が空港に立っていると想像してみてください。地理座標のペアが与えられた場合、どの空港にいるのかを効率的に判断するにはどうすればよいですか?

入力

  • 立っている場所を表す_(x,y)_の座標ペア。
  • 座標ペアのセット[(a1,b1), (a2,b2)...]ここで、各座標ペアは1つの空港を表します。

必要な出力

ポイント_(a,b)_に最も近い空港を表す空港座標ペアのセットからの座標ペア_(x,y)_。

非効率的なソリューション

この問題を解決するための非効率的な試みを以下に示します。空港セットの長さは明らかに直線的です。

_shortest_distance = None
shortest_distance_coordinates = None

point = (50.776435, -0.146834)

for airport in airports:
    distance = compute_distance(point, airport)
    if distance < shortest_distance or shortest_distance is None:
        shortest_distance = distance
        shortest_distance_coordinates = airport
_

質問

このソリューションはどのように改善できますか?これには、現在立っている場所の座標に基づいて空港のリストを事前にフィルタリングしたり、事前に特定の順序でソートしたりする方法が含まれる場合があります。

12
Kieran

座標が並べ替えられていない場合、(latitude,longitude)最初に地球と同様に緯度でフィルタリングする

球の緯度1度は111.2 kmまたは69マイル

しかし、それは大きなスピードアップを与えることはありません。

最初に空港を緯度で並べ替えると、バイナリ検索を使用してcouldに一致する最初の空港を見つけることができます(airport_lat >= point_lat-tolerance)そして、最後のcouldに一致するものだけを比較します(airport_lat <= point_lat+tolerance)-ただし、0度が360に等しいことに注意してください。このライブラリを直接使用することはできませんが、 bisect のソースは、バイナリ検索の実装に適しています。

技術的にはこのようにして検索は依然としてO(n)ですが、実際の距離の計算(許容差による)ははるかに少なく、緯度の比較はほとんどありません。だからあなたは巨大なスピードアップをするでしょう。

2
janbrohl

K次元ツリーの使用:

>>> from scipy import spatial
>>> airports = [(10,10),(20,20),(30,30),(40,40)]
>>> tree = spatial.KDTree(airports)
>>> tree.query([(21,21)])
(array([ 1.41421356]), array([1]))

ここで、1.41421356はクエリされたポイントと最近傍点の間の距離であり、1は近傍のインデックスです。

参照: http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.KDTree.query.html#scipy.spatial.KDTree.query

13
Juddling

これから SO質問

_import numpy as np
def closest_node(node, nodes):
    nodes = np.asarray(nodes)
    deltas = nodes - node
    dist_2 = np.einsum('ij,ij->i', deltas, deltas)
    return np.argmin(dist_2)
_

ここで、nodeは2つの値(x、y)を持つタプルであり、nodesは2つの値を持つタプルの配列です([(x_1, y_1), (x_2, y_2),]

2
J. C. Rocamonde