如何在python上找到经度和纬度点最近的邻居?

And*_*rei 8 python geolocation kdtree nearest-neighbor scipy

输入:

point = (lat, long)
places = [(lat1, long1), (lat2, long2), ..., (latN, longN)]
count = L
Run Code Online (Sandbox Code Playgroud)

输出: neighbors = places接近的子集point。(len(neighbors)=L

问: 我可以用kd树的快速最近邻小号查找与纬度和经度点?(例如,在scipy中实现)

是否有必要在坐标x,y中转换该点的地理坐标(纬度和经度)?

这是解决此问题的最佳方法吗?

Mar*_*son 5

老实说,我不知道使用 kd 树是否可以正常工作,但我的直觉表明它是不准确的。

\n\n

我认为你需要使用更大的圆距离之类的东西来获得准确的距离。

\n\n
\nfrom math import radians, cos, sin, asin, sqrt, degrees, atan2\n\ndef validate_point(p):\n    lat, lon = p\n    assert -90 <= lat <= 90, "bad latitude"\n    assert -180 <= lon <= 180, "bad longitude"\n\n# original formula from  http://www.movable-type.co.uk/scripts/latlong.html\ndef distance_haversine(p1, p2):\n    """\n    Calculate the great circle distance between two points \n    on the earth (specified in decimal degrees)\n    Haversine\n    formula: \n        a = sin\xc2\xb2(\xce\x94\xcf\x86/2) + cos \xcf\x861 \xe2\x8b\x85 cos \xcf\x862 \xe2\x8b\x85 sin\xc2\xb2(\xce\x94\xce\xbb/2)\n                        _   ____\n        c = 2 \xe2\x8b\x85 atan2( \xe2\x88\x9aa, \xe2\x88\x9a(1\xe2\x88\x92a) )\n        d = R \xe2\x8b\x85 c\n\n    where   \xcf\x86 is latitude, \xce\xbb is longitude, R is earth\xe2\x80\x99s radius (mean radius = 6,371km);\n            note that angles need to be in radians to pass to trig functions!\n    """\n    lat1, lon1 = p1\n    lat2, lon2 = p2\n    for p in [p1, p2]:\n        validate_point(p)\n\n    R = 6371 # km - earths\'s radius\n\n    # convert decimal degrees to radians \n    lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])\n\n    # haversine formula \n    dlon = lon2 - lon1\n    dlat = lat2 - lat1\n\n    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2\n    c = 2 * asin(sqrt(a)) # 2 * atan2(sqrt(a), sqrt(1-a))\n    d = R * c\n    return d\n
Run Code Online (Sandbox Code Playgroud)\n

  • 这个答案有点不完整,没有回答OP的问题。函数“distance_havesine()”计算以纬度/经度给出的两点之间的距离(以公里为单位),但它没有回答如何使用该度量找到最近邻居的问题。 (3认同)
  • @MarcelWilson啊,是的,你是对的,你的答案可以很容易地用来计算所有成对距离,然后取最小值。这是可能的,但不是最佳的。对于较大的值(假设 &gt;10 000 点),这将使用大量内存并花费大量时间。它需要 O(n^2) 时间和内存,而最佳解决方案应该是 O(n*log(n)) 时间,例如使用某种索引,如 k 树。由于 OP 询问了 k 树,我认为他对最优解决方案感兴趣。 (2认同)

Flo*_*ker 5

scikit-learn提供BallTree支持半正矢度量的类。另请参阅这个问题