我有以下两个数据集:
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))
我想将houses
和stations
合并在一起,使生成的station_number
是最接近相应house_number
的电台。
This question is very similar,但我不确定它们是否适用于经度和纬度,而且我不知道在处理经度和纬度时如何计算距离(这就是为什么我更喜欢简单地使用distm
包中的geosphere
。
我从未使用过外部函数。如果上述问题的答案可行,我该如何调整答案以使用distm
函数而不是sqrt
函数?
答案 0 :(得分: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.
答案 1 :(得分:1)
使用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。