【问题标题】:What is the most efficient way to find the closest geographic location?找到最近的地理位置最有效的方法是什么?
【发布时间】:2020-11-27 11:55:41
【问题描述】:

我有两个数据框,其中的观测值是由纬度/经度组合定义的地理位置。对于df1 中的每个点,我想获取df2 中的最近点以及相关值。我知道如何通过计算所有可能的距离(例如使用 Imap 包中的 gdist 函数)并获取最小距离的索引来做到这一点。但事实是,df1 有 1000 行,df2 大约有 1500 万行,它充其量是过长的。

您知道如何在不计算所有距离的情况下达到目标吗?也许有办法限制必要的计算(例如使用纬度/经度值的差异)?

感谢您的帮助,

这是df1的样子:

   Latitude Longitude
1  56.76342  8.320824
2  54.93165  9.115982
3  55.80685  9.102455
4  57.27000  9.760000
5  56.76342  8.320824
6  56.89333  9.684435
7  56.62804  8.571573
8  56.64850  8.501947
9  55.40596  8.884374
10 54.89786 11.880828

然后df2:

   Latitude Longitude       Value
1  41.91000 -4.780000       40500
2  41.61063 14.750832       13500
3  41.91000 -4.780000        4500
4  38.70000 -2.350000       28500
5  52.55172  0.088622        1500
6  39.06000 -1.830000       51000
7  41.91000 -4.780000       49500
8  48.00623 -4.389639       12000
9  56.24889 -3.666940       27000
10 42.72000 -3.750000       49500

【问题讨论】:

  • 简单的方法:使用支持 GIS 的数据库(例如 postgreSQL 的 postGIS 插件)。您也可以使用 GIS 软件(您的任务是 GIS 中最常见的任务之一,除了可视化)。否则你“索引”数据:你建立扇区,你只检查同一扇区中的数据,或者 ev。您搜索附近的部门,并只在那里进行搜索。 [EV。更多层次]。当然有更好的算法。我总是预处理数据
  • 这可能会让你朝着正确的方向前进:stackoverflow.com/questions/57525670/…
  • 另一个取决于您的应用程序和所需精度的选项是将纬度和经度从 5 位精度向下舍入到 2 或 3 位,然后将匹配的起点组合在一起。
  • 谢谢!我设法通过使用raster 包来做到这一点。我得到了每个数据库中每个点对应的区域,然后计算了每个特定点与df1df2 中与同一区域相关联的点之间的距离。

标签: r gis


【解决方案1】:

将第二帧分成大小相等的块

然后只搜索你的点合理距离内的块。您将基本上在地图上绘制棋盘格。您的点将在这些方格之一内 - 因此您将只搜索那个和少数几个相邻的方格以确保安全。

天真的蛮力搜索是行(df1)*行(df2)。在我们的例子中是 1000 * 15M,使得 15G 操作乘以每次操作的计算时间。

那么我们如何将数据拆分成块呢?

  1. 按纬度排序
  2. 按经度排序
  3. 采用等间距的块

排序需要一些 Nlog(N) 操作。在我们的例子中,N 是 15M,所以这两种类型需要 ~2415M2 次操作。分割成块然后是线性的 ~15M 操作,可能是几次。
当你完成这种分离后,在每个块中你都有total_points/(chunk_side ^ 2) 点,假设你的点是平均分布的。 块的数量与开始时块的大小成正比: total_area/(chunk_side ^ 2).

理想情况下,您希望平衡块的数量和每个块中的点数,以便两者都是 ~sqrt(points_total)

现在每千次搜索只需要chunk_count + points_in_chunk * 9(如果我们想要超级安全并搜索我们的点所在的块以及所有周围的块。)所以现在你有 ` 而不是 1000 * 15M 1000 * (sqrt(15M) *18) ~ 1000 * 16K,提高了 50 倍。

请注意,如果第二组变得更大,这种改进将会增加。如果你选择的块大小不好,改进也会更小。
为了进一步改进,您可以再迭代一次或两次,将块分成块。逻辑类似。

【讨论】:

    【解决方案2】:

    geosphere 包的distm 函数将帮助您:

    # Make sure to put longitude first and then latitude:
    df <- df %>%  select(Longitude,Latitude) 
    
    library(geosphere)
    distm(as.matrix(df), as.matrix(df), fun=distGeo)
    

    请记住,distm 函数接受 matrix 类对象。您将获得一个 10x10 的距离矩阵。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      • 2017-05-10
      • 2012-05-13
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 2016-07-11
      相关资源
      最近更新 更多