【问题标题】:Match two datasets by minimum geospatial distance (R)按最小地理空间距离 (R) 匹配两个数据集
【发布时间】:2019-02-09 22:47:35
【问题描述】:

我有以下两个数据集:

houses <- data.table(house_number = c(1:3),
                     lat_decimal = seq(1.1, 1.3, by = 0.1),
                     lon_decimal = seq(1.4, 1.6, by = 0.1))
stations <- data.table(station_numer = c(1:11),
                       lat_decimal = seq(1, 2, by = 0.1),
                       lon_decimal = seq(2, 3, by = 0.1))

我想将housesstations 合并在一起,这样生成的station_number 就是最接近相应house_number 的站。

This question is very similar,但我不确定他们是否正在处理经纬度,而且我不知道在处理经度和纬度时如何计算距离(这就是为什么我更喜欢简单地使用 @ 987654327@ 来自geosphere 包)。

我从未使用过外部函数。如果上述问题的答案有效,我该如何调整答案以使用distmfunction 而不是sqrtfunction?

【问题讨论】:

    标签: r geosphere


    【解决方案1】:

    使用来自hutilscppmatch_nrst_haversine

    library(hutilscpp)
    houses[, c("station_number", "dist") := match_nrst_haversine(lat_decimal,
                                                                 lon_decimal,
                                                                 addresses_lat = stations$lat_decimal,
                                                                 addresses_lon = stations$lon_decimal,
                                                                 Index = stations$station_numer,
                                                                 close_enough = 0,
                                                                 cartesian_R = 5)]
    
    houses
    #>    house_number lat_decimal lon_decimal station_number     dist
    #> 1:            1         1.1         1.4              1 67.62617
    #> 2:            2         1.2         1.5              1 59.87076
    #> 3:            3         1.3         1.6              1 55.59026
    

    如果您的数据很多(即超过一百万个匹配点)以提高性能,您可能需要调整 close_enoughcartesian_R

    `cartesian_R`
    

    任何地址距要进行地理编码的点的最大半径。用于加速最小距离的检测。注意,作为 参数名称表明,距离是笛卡尔坐标,所以 可能是少数。

    `close_enough`    
    

    以米为单位的距离,低于该距离将被视为已发生匹配。 (被认为“足够近”的距离是 匹配。)

    例如,close_enough = 10 表示将匹配十米内的第一个位置,即使稍后出现更接近的匹配。

    可以作为字符串提供以强调单位,例如close_enough = "0.25 公里"。只允许使用 km 和 m。

    【讨论】:

      【解决方案2】:

      你的问题比简单的合并要复杂一些,outer 有点不适合这个目的。为了尽可能彻底,我们要计算房屋和车站的所有组合之间的距离,然后只保留每栋房屋最近的车站。我们需要两个包:

      library(tidyverse)
      library(geosphere)
      

      首先,做一点准备。 distm 期望坐标的顺序是经度第一,纬度第二(你有相反的情况),所以让我们解决这个问题,更好地命名列,并在我们处理时纠正错字:

      houses <- data.frame(house_number = c(1:3),
                           lon_house = seq(1.4, 1.6, by = 0.1),
                           lat_house = seq(1.1, 1.3, by = 0.1)
                           )
      stations <- data.frame(station_number = c(1:11),
                             lon_station = seq(2, 3, by = 0.1),
                             lat_station = seq(1, 2, by = 0.1)
                             )
      

      我们将创建“嵌套”数据框,以便更轻松地将坐标保持在一起:

      house_nest <- nest(houses, -house_number, .key = 'house_coords')
      station_nest <- nest(stations, -station_number, .key = 'station_coords')
      
        house_number house_coords        
               <int> <list>              
      1            1 <data.frame [1 × 2]>
      2            2 <data.frame [1 × 2]>
      3            3 <data.frame [1 × 2]>
      
         station_number station_coords      
                  <int> <list>              
       1              1 <data.frame [1 × 2]>
       2              2 <data.frame [1 × 2]>
       3              3 <data.frame [1 × 2]>
       4              4 <data.frame [1 × 2]>
       5              5 <data.frame [1 × 2]>
       6              6 <data.frame [1 × 2]>
       7              7 <data.frame [1 × 2]>
       8              8 <data.frame [1 × 2]>
       9              9 <data.frame [1 × 2]>
      10             10 <data.frame [1 × 2]>
      11             11 <data.frame [1 × 2]>
      

      使用dplyr::crossing 合并两个数据帧中的每一行:

      data.master <- crossing(house_nest, station_nest)
      
         house_number house_coords         station_number station_coords      
                <int> <list>                        <int> <list>              
       1            1 <data.frame [1 × 2]>              1 <data.frame [1 × 2]>
       2            1 <data.frame [1 × 2]>              2 <data.frame [1 × 2]>
       3            1 <data.frame [1 × 2]>              3 <data.frame [1 × 2]>
       4            1 <data.frame [1 × 2]>              4 <data.frame [1 × 2]>
       5            1 <data.frame [1 × 2]>              5 <data.frame [1 × 2]>
       6            1 <data.frame [1 × 2]>              6 <data.frame [1 × 2]>
       7            1 <data.frame [1 × 2]>              7 <data.frame [1 × 2]>
       8            1 <data.frame [1 × 2]>              8 <data.frame [1 × 2]>
       9            1 <data.frame [1 × 2]>              9 <data.frame [1 × 2]>
      10            1 <data.frame [1 × 2]>             10 <data.frame [1 × 2]>
      # ... with 23 more rows
      

      现在所有这些都到位了,我们可以在每一行上使用distm 来计算距离,并保持每间房子的最短距离:

      data.dist <- data.master %>% 
        mutate(dist = map2_dbl(house_coords, station_coords, distm)) %>% 
        group_by(house_number) %>% 
        filter(dist == min(dist))
      
        house_number house_coords         station_number station_coords         dist
               <int> <list>                        <int> <list>                <dbl>
      1            1 <data.frame [1 × 2]>              1 <data.frame [1 × 2]> 67690.
      2            2 <data.frame [1 × 2]>              1 <data.frame [1 × 2]> 59883.
      3            3 <data.frame [1 × 2]>              1 <data.frame [1 × 2]> 55519.
      

      【讨论】:

        猜你喜欢
        • 2017-11-07
        • 2018-01-19
        • 2016-04-10
        • 1970-01-01
        • 2017-05-09
        • 2018-09-26
        • 2019-04-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多