1

我有以下两个数据集:

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.

这个问题非常相似,但我不确定他们是否正在使用纬度和经度,而且我不知道在处理经度和纬度时如何计算距离(这就是为什么我更喜欢简单地使用distmfromgeosphere包裹)。

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

4

2 回答 2

2

使用match_nrst_haversine来自hutilscpp

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_enough您可能需要进行调整以提高性能。cartesian_R

`cartesian_R`

从要进行地理编码的点开始的任何地址的最大半径。用于加速最小距离的检测。请注意,正如参数名称所暗示的,距离是在笛卡尔坐标中,所以可能是一个小数字。

`close_enough`    

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

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

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

于 2019-02-09T14:47:35.760 回答
1

您的问题比简单的合并要复杂一些,并且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.
于 2019-02-09T14:43:38.927 回答