0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonその4Advent Calendar 2019

Day 3

Pythonのgeoindexライブラリで近くの緯度経度の点を取得する

Last updated at Posted at 2019-12-17

このように、緯度経度を表す数値のtupleが入ったリストから、指定した緯度経度で最も近い点を判定したいとします。

geo_pts = [
    (35.60, 139.71),
    (35.58, 139.82),
    # 以下略
]

ナイーブな実装

リストの中身をすべて計算するナイーブな実装です。

import math

def find(geo_pts, target):
    return max(geo_pts, key=lambda p: dist(p, target))

def dist(p1, p2):
    return math.sqrt(sum((x1 - x2) ** 2 for x1, x2 in zip(p1, p2)))

こんな挙動です。AWSのEC2 t2.mediumインスタンスで、15000個程度の点を探すのに20ms程度かかってしまいました。

print(find(geo_pts, (35.6, 139.7)))
# => (35.60, 139.71)

ちなみに、n個取得したい場合は、 heapq.nlargest が使えます。

geoindexライブラリでの実装

def main():
    geo_pts = [
      # 配列で読み込み
    ]
    index = GeoGridIndex(precision=4)
    for x in geo_pts:
        index.add_point(GeoPoint(x[0], x[1]))

    prev = time.time()
    print(find(index, (35.6, 139.7)))
    # => (Point(35.687659999999994, 139.71178), 9.80482739300054)
    print(time.time() - prev)



def find(index, target):
    return next(index.get_nearest_points(GeoPoint(*target), 10, 'km'))

AWSのEC2 t2.mediumインスタンスで、こちらの実装では4ms程度で値が返ってきました。

ちなみに、 GeoGridIndex の引数のCell Sizeの単位はkmで、 precision=4 を指定した場合は半径40/2=20kmの範囲以内で検索できます。私の要件では半径20kmでちょうどよかったため、これ以上の検証は行っていません。

Precision Cell size
1 5000
2 1260
3 156
4 40
5 4.8
6 1.22
7 0.152
8 0.038
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?