【问题标题】:Find Distance to Nearest GPS Coordinates (Nearest Neighbors Search)查找到最近 GPS 坐标的距离(最近邻搜索)
【发布时间】:2018-02-06 07:05:22
【问题描述】:

我有一个包含纬度和经度元组的数据框,如下所示(实际坐标示例):

    id    latlon             
67  79    (39.1791764701497, -96.5772313693982)
68  17    (39.1765194942359, -96.5677757455844)
69  76    (39.1751440428827, -96.5772939901891)
70  58    (39.175359525189, -96.5691986655256)
71  50    (39.1770962912298, -96.5668107589661)

我想在同一个数据框中找到id 和最近的latlon 的距离(为了说明,我只是在nearest_idnearest_dist 列中组成以下数字):

    id    latlon                                  nearest_id  nearest_dist
67  79    (39.1791764701497, -96.5772313693982)   17          37          
68  17    (39.1765194942359, -96.5677757455844)   58          150           
69  76    (39.1751440428827, -96.5772939901891)   50          900          
70  58    (39.175359525189, -96.5691986655256)    17          12          
71  50    (39.1770962912298, -96.5668107589661)   79          4      

我有大量 (45K+) 坐标,我想在这些坐标上执行此操作。

下面是我尝试的解决方案,使用来自geopy.distancesgreat_circle

def great_circle_dist(latlon1, latlon2):
    """Uses geopy to calculate distance between coordinates"""
    return great_circle(latlon1, latlon2).meters

def find_nearest(x):
        """Finds nearest neighbor """
        df['distances'] = df.latlon.apply(great_circle_dist, args=(x,))
        df_sort = df.sort_values(by='distances')
        return (df_sort.values[1][0], df_sort.values[1][2])

df['nearest'] = df['latlon'].apply(find_nearest)
df['nearest_id'] = df.nearest.apply(lambda x: x[0])
df['nearest_dist'] = df.nearest.apply(lambda x: x[1])
del df['nearest']
del df['distances']

可以做些什么来有效地进行这种计算?

【问题讨论】:

    标签: python pandas gis geopandas


    【解决方案1】:

    您可以使用 PostGIS/PostgreSQL 高效地执行此操作,但是您必须将数据放入 sql 表中,这可能很困难。您可以从 python 发出 postgresql 命令,但您仍然需要设置后端。希望有人能够为您提供有关如何仅使用 python 使用它的提示。

    【讨论】:

      【解决方案2】:

      空间索引应该会有所帮助。

      您可以使用数据库(例如带有 PosGIS 扩展的 Postgres)实现空间索引,但您也可以使用内存解决方案。

      看看Rtree 库。您需要创建索引,将所有点添加到索引中,然后使用nearest 方法查询索引。

      【讨论】:

        【解决方案3】:

        'scipy.spatial' 有许多有用的(而且速度极快)的空间搜索算法。似乎适合您的问题的工具是“cKDTree”。

        tree = cKDTree(data)
        

        数据应该是一个形状为 n*2 的 numpy 数组(它可以计算 n 维空间中的距离,但在这种情况下我们有两个维度)

        然后你可以查询树的k个最近邻居:

        dist, idx = tree.query(x, k=1)
        

        使用索引,获取id应该很简单。我回答了一个类似的问题here。另请查看 cmets 了解有关投影的信息。

        【讨论】:

        • 这里使用cKDTree会不会假设输入是笛卡尔坐标?
        • @JosephDasenbrock 是的。您可以使用“pyproj”将坐标从 lon/lat 投影到 UTM(或任何其他适合测量的投影),或者使用大圆甚至更好的半正弦公式作为 scipy.spatial.distance 的自定义距离度量。。第二种方法在same question 的另一个解决方案中进行了解释
        • cKDTree 是 100% 准确,还是一种优先考虑速度而不是完全准确的搜索算法?
        • @JosephDasenbrock 确切地说,这不是启发式的。如果您愿意,您可以在 'query()' 中指定 'eps' 参数为正数,这会加快搜索速度但会返回近似邻居。默认为零,这意味着确切的邻居。
        猜你喜欢
        • 2016-10-31
        • 2012-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-12
        • 2018-06-16
        • 1970-01-01
        相关资源
        最近更新 更多