【问题标题】:KDTree for longitude/latitude经度/纬度的KDTree
【发布时间】:2012-05-19 22:25:58
【问题描述】:

Python 中是否有任何软件包允许对球体表面的经度/纬度进行类似 kdtree 的操作? (这需要适当考虑球面距离以及经度环绕)。

【问题讨论】:

    标签: python data-structures latitude-longitude kdtree


    【解决方案1】:

    二叉搜索树无法通过设计处理极性表示的环绕。您可能需要将坐标转换为 3D 笛卡尔空间,然后应用您喜欢的搜索算法,例如 kD-Tree、Octree 等。

    或者,如果您可以将坐标的输入范围限制在表面上的一个小区域,您可以对该区域应用适当的地图投影,即不会过度扭曲您所在区域的形状,然后应用这些无环绕笛卡尔地图坐标上的标准二叉搜索树。

    【讨论】:

    • 你所说的“环绕”是纵向的吗?如果是这样,你能解释一下为什么二叉树不能处理它而 3D 空间可以吗?
    • @pstatix 我指的是像 kd-tree 这样的有序二叉树,它将超平面上的数据集拆分为子空间。当坐标环绕时,例如极坐标中的角度,这不起作用,因为相关点可能在两端。显然,有基于距离计算进行细分的二叉树,而不是在超平面上进行拆分,例如 Ball Tree。所以这实际上可能是我当时不知道的一个选项。
    【解决方案2】:

    我相信来自 scikit-learn 的 BallTree 与 Haversine 指标应该可以为您解决问题。

    举个例子:

    from sklearn.neighbors import BallTree
    import numpy as np
    import pandas as pd
    
    cities = pd.DataFrame(data={
        'name': [...],
        'lat': [...],
        'lon': [...]
    })
    
    query_lats = [...]
    query_lons = [...]
    
    bt = BallTree(np.deg2rad(cities[['lat', 'lon']].values), metric='haversine')
    distances, indices = bt.query(np.deg2rad(np.c_[query_lats, query_lons]))
    
    nearest_cities = cities['name'].iloc[indices]
    

    请注意,这会返回假设半径为 1 的球体的距离 - 将地球上的距离乘以半径 = 6371km

    见:

    【讨论】:

    • 效果很好,除了 1 件事,请注意,通过半正弦度量计算的距离假定球体的半径为 1,因此您需要乘以半径 = 6371km 才能获得实际距离。 scikit-learn.org/stable/modules/generated/… 我认为这与 moooeeeep 的回答中转换为 3D 笛卡尔坐标之间的总体计算/节省的时间可能没有太大区别,但这应该节省一些空间,而不必存储 3D 坐标
    猜你喜欢
    • 2013-09-09
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    • 2013-02-21
    相关资源
    最近更新 更多