【问题标题】:Crossing two sets of coordinates in order to calculate minimum distance? (tidyr geosphere R)交叉两组坐标以计算最小距离? (tidyr geosphere R)
【发布时间】:2021-01-29 09:38:57
【问题描述】:

我在同一个有界区域中有一组 2,220 个巢坐标 (var1) 和另一组 26 个地标坐标 (var2)。我想找到 2,224 个坐标中的每一个到 26 个集合中的每个点之间的距离,以便创建一个包含列的新数据框(嵌套坐标、最小距离地标坐标、以 m 为单位的距离)。

我被困在试图交叉这两个集合以生成一个集合,其中所有地标坐标都与每个巢坐标配对。

**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 个地标坐标之一以及两点。从那里,我将选择距离最小的行。

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)

看起来应该很容易解决,任何帮助将不胜感激。

【问题讨论】:

  • 请使用dput()提供您的数据样本
  • @rjen 这行得通,而且比我的解决方案快很多,谢谢!

标签: r matrix dplyr tidyr geosphere


【解决方案1】:

使用我为该场合制作的数据和数据格式,您可以执行以下操作。

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))

【讨论】:

    猜你喜欢
    • 2022-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    相关资源
    最近更新 更多