交叉两组坐标以计算最小距离? (tidyr geosphere R)
Crossing two sets of coordinates in order to calculate minimum distance? (tidyr geosphere R)
我在同一边界区域中有一组 2,220 个巢坐标 (var1) 和另一组 26 个地标坐标 (var2)。我想找到 2,224 个坐标中的每一个与 26 个坐标中的每个点之间的距离,以便创建一个包含列的新数据框(巢坐标、最小距离地标坐标、以米为单位的距离)。
我一直在尝试交叉这两个集合以生成一个集合,其中所有地标坐标都与每个嵌套坐标配对。
**nest** **landmark** **distance**
lat1, lon1 lat1, lon1 34
lat1, lon1 lat2, lon2 18
lat1, lon1 lat3, lon3 82
....
lat1, lon1 lat26,lon26 61
lat2, lon2 lat1, lon1 94
lat2, lon2 lat2, lon2 38
...
lat2,220, lon 2,220 lat 26,lon26 46
我尝试过 crossing(var1, var2),其中 var1 和 var2 都是包含纬度和经度值的矩阵,然后计算每个结果行之间的 Haversine 距离(见下文)。这似乎行得通,但我认为它并没有给我预期的确切结果。交叉得到的行数与这些集合的 nrow 的乘积不一致。
我还希望能够将具有所有距离值的结果集分成 26 组,其中每组包含嵌套坐标(对每一行重复)、26 个地标坐标之一和距离两点之间。从那里,我将 select 用于最小距离的行。
newset <- crossing(nests, landmarks)
mindist <- distHaversine(newset[1], newset[2], r=6378137)
newsetwdist <- cbind(newset, mindist)
sv <- split(newsetwdist,rep(1:56056,each=26))
#56056 was the resulting number of rows, even though I expected 57,720.
var3 <- lapply(sv, "[", 3) #returns a nested list of all distances for each nest
var4 <- lapply(var2, "[[", "mindist")
df = as.data.frame(do.call(rbind, lapply(var4, unlist)))
min.dist.from.landmark <- apply(df, 1, FUN=min)
看来这应该是一个简单的修复,我们将不胜感激。
使用我为此制作的数据和数据格式,您可以执行以下操作。
library(dplyr)
library(purrr)
library(tidyr)
library(geosphere)
crossing(nest, landmark) %>%
mutate(nest_long_lat = map2(nest_long, nest_lat, ~ c(.x, .y)),
mark_long_lat = map2(mark_long, mark_lat, ~ c(.x, .y)),
distance = unlist(map2(mark_long_lat, nest_long_lat, ~ distGeo(.x, .y)))) %>%
group_by(nest_long_lat) %>%
mutate(min_distance = distance == min(distance)) %>%
ungroup() %>%
select(-nest_long_lat, -mark_long_lat)
# # A tibble: 57,720 x 6
# nest_lat nest_long mark_lat mark_long distance min_distance
# <dbl> <dbl> <dbl> <dbl> <dbl> <lgl>
# 1 46.5 49.1 48.4 49.8 215350. TRUE
# 2 46.5 49.1 48.6 48.7 229592. FALSE
# 3 46.5 49.1 48.8 49.9 255689. FALSE
# 4 46.5 49.1 48.9 48.4 268789. FALSE
# 5 46.5 49.1 49.3 50.1 312691. FALSE
# 6 46.5 49.1 49.3 49.2 309549. FALSE
# 7 46.5 49.1 49.6 51.6 390862. FALSE
# 8 46.5 49.1 49.7 50.8 371686. FALSE
# 9 46.5 49.1 49.8 50.6 377182. FALSE
# 10 46.5 49.1 49.9 49.9 376530. FALSE
# # … with 57,710 more rows
数据
nest <- tibble(nest_lat = rnorm(50, n = 2220),
nest_long = rnorm(50, n = 2220))
landmark <- tibble(mark_lat = rnorm(50, n = 26),
mark_long = rnorm(50, n = 26))
我在同一边界区域中有一组 2,220 个巢坐标 (var1) 和另一组 26 个地标坐标 (var2)。我想找到 2,224 个坐标中的每一个与 26 个坐标中的每个点之间的距离,以便创建一个包含列的新数据框(巢坐标、最小距离地标坐标、以米为单位的距离)。
我一直在尝试交叉这两个集合以生成一个集合,其中所有地标坐标都与每个嵌套坐标配对。
**nest** **landmark** **distance**
lat1, lon1 lat1, lon1 34
lat1, lon1 lat2, lon2 18
lat1, lon1 lat3, lon3 82
....
lat1, lon1 lat26,lon26 61
lat2, lon2 lat1, lon1 94
lat2, lon2 lat2, lon2 38
...
lat2,220, lon 2,220 lat 26,lon26 46
我尝试过 crossing(var1, var2),其中 var1 和 var2 都是包含纬度和经度值的矩阵,然后计算每个结果行之间的 Haversine 距离(见下文)。这似乎行得通,但我认为它并没有给我预期的确切结果。交叉得到的行数与这些集合的 nrow 的乘积不一致。
我还希望能够将具有所有距离值的结果集分成 26 组,其中每组包含嵌套坐标(对每一行重复)、26 个地标坐标之一和距离两点之间。从那里,我将 select 用于最小距离的行。
newset <- crossing(nests, landmarks)
mindist <- distHaversine(newset[1], newset[2], r=6378137)
newsetwdist <- cbind(newset, mindist)
sv <- split(newsetwdist,rep(1:56056,each=26))
#56056 was the resulting number of rows, even though I expected 57,720.
var3 <- lapply(sv, "[", 3) #returns a nested list of all distances for each nest
var4 <- lapply(var2, "[[", "mindist")
df = as.data.frame(do.call(rbind, lapply(var4, unlist)))
min.dist.from.landmark <- apply(df, 1, FUN=min)
看来这应该是一个简单的修复,我们将不胜感激。
使用我为此制作的数据和数据格式,您可以执行以下操作。
library(dplyr)
library(purrr)
library(tidyr)
library(geosphere)
crossing(nest, landmark) %>%
mutate(nest_long_lat = map2(nest_long, nest_lat, ~ c(.x, .y)),
mark_long_lat = map2(mark_long, mark_lat, ~ c(.x, .y)),
distance = unlist(map2(mark_long_lat, nest_long_lat, ~ distGeo(.x, .y)))) %>%
group_by(nest_long_lat) %>%
mutate(min_distance = distance == min(distance)) %>%
ungroup() %>%
select(-nest_long_lat, -mark_long_lat)
# # A tibble: 57,720 x 6
# nest_lat nest_long mark_lat mark_long distance min_distance
# <dbl> <dbl> <dbl> <dbl> <dbl> <lgl>
# 1 46.5 49.1 48.4 49.8 215350. TRUE
# 2 46.5 49.1 48.6 48.7 229592. FALSE
# 3 46.5 49.1 48.8 49.9 255689. FALSE
# 4 46.5 49.1 48.9 48.4 268789. FALSE
# 5 46.5 49.1 49.3 50.1 312691. FALSE
# 6 46.5 49.1 49.3 49.2 309549. FALSE
# 7 46.5 49.1 49.6 51.6 390862. FALSE
# 8 46.5 49.1 49.7 50.8 371686. FALSE
# 9 46.5 49.1 49.8 50.6 377182. FALSE
# 10 46.5 49.1 49.9 49.9 376530. FALSE
# # … with 57,710 more rows
数据
nest <- tibble(nest_lat = rnorm(50, n = 2220),
nest_long = rnorm(50, n = 2220))
landmark <- tibble(mark_lat = rnorm(50, n = 26),
mark_long = rnorm(50, n = 26))