【问题标题】:Calculate distance between coordinates in R计算R中坐标之间的距离
【发布时间】:2021-09-08 04:47:49
【问题描述】:

我想计算我的数据帧的纬度/经度位置之间的距离(以米为单位),但有以下限制: 1.- 只有相同 CLIENTID 的纬度/经度,但它们之间都相同。 2.- 为每个 CLIENTID 生成一个新的数据帧(并导出到 CSV o XLS)

我的数据存储为:

| CLIENT ID | HOUSE ID | LAT | LONG |
| 111111111 | xxx111   | xx.xx| xx.xx|
| 111111111 | xxx112   | xx.xx| xx.xx|
| 111111111 | xxx145   | xx.xx| xx.xx|
| 222222222 | xxx345   | xx.xx| xx.xx|
| 222222222 | xxx 666  | xx.xx| xx.xx|

我需要什么:

以 CLIENTID (CLIENTID.csv) 命名的 CSV 或 XLS 文件,内容如下:

| CLIENT ID | HOUSE ID1 | HOUSE ID 2| DISTANCE |
| 111111111 | xxx111    | xxx112    | 950      | 
| 111111111 | xxx111    | xxx145    | 750      |
| 111111111 | xxx112    | xxx145    | 250      |

我尝试了一些链接,但我不知道如何解决它,因为我已经与计算机断开连接一年了 (COVID)

链接:

Calculating distance between two GPS locations in a data frame using distm () in R

Function to calculate geospatial distance between two points (lat,long) using R

编辑:添加数据

对不起,我的第一篇文章。我完全被屏蔽了,无法以适当的方式提问。

我已经组合了两个数据帧(leftjoin)以获得带有“Doc_titular”的 AAA_JOIN 数据帧

现在我的问题开始了:
1.- 从“Doc_titular”过滤,并从同一个“Doc_titular”中获取所有行
2.- 计算所有 LAT/LONG 之间的距离 3.- 将每个“Doc_titular”的数据存储在 CSV 中,所有 HouseID 距离均采用上述格式(Doc_titular; HouseId; HouseId(n); Meters)

以下是数据示例:

Doc_titular House_ID    longitude   latitude
26DF5756F   AAA/BA/00145    -3.36715925514947   3.80089929185657
26DF5756F   AAA/BA/00146    -3.36687508416913   3.80092746460019
26DF5756F   AAA/BA/00733    -3.37604382639631   3.80126114282085
45GH7765B   AAA/BA/00123    -3.36887798896237   3.80405033823961
45GH7765B   AAA/BA/00498    -3.37077717656959   3.80121749925945
45GH7765B   AAA/BA/00998    -3.79037050320006   3.77633839304628
45GH7765B   AAA/BA/00332    -3.38064351196704   3.80099089206718
98TR2794P   AAA/BA/00420    -3.36824907065489   3.80086791973886
98TR2794P   AAA/BA/00557    -3.37255900917349   3.80107792023686
98TR2794P   AAA/BA/00556    -3.36674589155523   3.8012204114931
98TR2794P   AAA/BA/00040    -4.05181620512371   3.80137173136896

对不起,如果我发布一些基本的东西,但我不太擅长 R,而且今年我在计算机方面还很遥远。 提前致谢。

【问题讨论】:

  • 如果您可以向我们提供可复制的minimal working example,我们可以复制和粘贴以更好地了解问题并测试可能的解决方案,这将很有帮助。您可以使用dput(YOUR_DATASET) 共享数据集,或者使用dput(head(YOUR_DATASET)) 共享较小的样本。 (请参阅 this answer 以获得一些很好的建议。)

标签: r gps sf


【解决方案1】:

这是我使用purrrgeosphere::distm() 的解决方案:

library(purrr)

split(your_data, ~ Doc_titular) %>%
  map(~ pmap(.x, list)) %>%
  map_dfr(~ combn(.x, 2, simplify = F) %>% map_dfr(~ do.call(\(h1, h2) {
    c(House_ID_1 = h1$House_ID,
      House_ID_2 = h2$House_ID,
      Distance = geosphere::distm(c(h1$longitude, h1$latitude),
                                  c(h2$longitude, h2$latitude)))
  }, .x)))

返回:

# A tibble: 15 x 3
   House_ID_1   House_ID_2   Distance        
   <chr>        <chr>        <chr>           
 1 AAA/BA/00145 AAA/BA/00146 31.7180146462883
 2 AAA/BA/00145 AAA/BA/00733 987.675672076512
 3 AAA/BA/00146 AAA/BA/00733 1019.09764067029
 4 AAA/BA/00123 AAA/BA/00498 377.66269306226 
 5 AAA/BA/00123 AAA/BA/00998 46918.5688963262
 6 AAA/BA/00123 AAA/BA/00332 1349.94747698525
 7 AAA/BA/00498 AAA/BA/00998 46688.6347143115
 8 AAA/BA/00498 AAA/BA/00332 1096.20190700286
 9 AAA/BA/00998 AAA/BA/00332 45593.1545475677
10 AAA/BA/00420 AAA/BA/00557 479.294723110493
11 AAA/BA/00420 AAA/BA/00556 171.456842525277
12 AAA/BA/00420 AAA/BA/00040 75928.0863123282
13 AAA/BA/00557 AAA/BA/00556 645.89145220337 
14 AAA/BA/00557 AAA/BA/00040 75449.3320106569
15 AAA/BA/00556 AAA/BA/00040 76095.0197361047

(使用的数据:)

your_data <- structure(list(Doc_titular = c("26DF5756F", "26DF5756F", "26DF5756F", "45GH7765B", "45GH7765B", "45GH7765B", "45GH7765B", "98TR2794P", "98TR2794P", "98TR2794P", "98TR2794P"), House_ID = c("AAA/BA/00145", "AAA/BA/00146", "AAA/BA/00733", "AAA/BA/00123", "AAA/BA/00498", "AAA/BA/00998", "AAA/BA/00332", "AAA/BA/00420", "AAA/BA/00557", "AAA/BA/00556", "AAA/BA/00040"), longitude = c(-3.36715925514947, -3.36687508416913, -3.37604382639631, -3.36887798896237, -3.37077717656959, -3.79037050320006, -3.38064351196704, -3.36824907065489, -3.37255900917349, -3.36674589155523, -4.05181620512371), latitude = c(3.80089929185657, 3.80092746460019, 3.80126114282085, 3.80405033823961, 3.80121749925945, 3.77633839304628, 3.80099089206718, 3.80086791973886, 3.80107792023686, 3.8012204114931, 3.80137173136896)), row.names = c(NA, -11L), class = c("tbl_df", "tbl", "data.frame"))

【讨论】:

  • 谢谢@ktiu
    我试过你的代码,我收到了这个消息Error: unexpected input in: " map_dfr(~ combn( 2, simplify = FALSE) %&gt;% map_dfr(~ do.call(\"我从来没有用过purrr,所以我不知道这个消息(即使我试过您的完整示例加载数据)提前致谢
  • 您收到此错误是因为您运行的是旧版本的 R。在我的代码中,我使用了 R v4.1 中引入的anonymous function notation。您可以通过升级到最新版本的 R 或将反斜杠符号 \() 替换为 function() 来解决此问题。
  • 谢谢@ktiu。我正在使用 R v4.0。更改function() 解决了此消息现在我得到Error in unique.default(x, nmax = nmax) : unique() only used with vectors 任何想法? (我的消息不是英文的)提前谢谢(再次)。
  • 由于您没有提供可重现的数据,我不得不对您的数据类型做出假设。这就是为什么在您的问题中包含示例数据是个好主意(使用dput()
  • 对不起@ktiu,但是数据对于在互联网上发布非常敏感。