【问题标题】:Computing distances using distCosine使用 distCosine 计算距离
【发布时间】:2017-03-30 15:13:32
【问题描述】:

我想计算 (lat,lon) 坐标对之间的距离,如下例所示: Calculating distances from latitude and longitude coordinates in R

但使用 dplyr 来加快处理速度,并使用 geosphere 中的 distCosine 函数。

这个函数只接受大小为 2 的向量,我发现唯一可行的方法是:

p <- data.frame(lat=runif(6,-90,90), lon=runif(6,-180,180),lat2=runif(6,-90,90), lon2=runif(6,-180,180) )
p$dist <- sapply(1:nrow(p), function(x) distCosine(c(p$lon[x], p$lat[x]), c(p$lon2[x], p$lat2[x]) ) )

我已经尝试过使用 dplyr:

p %>% rowwise() %>% mutate(dist2prev = distCosine(c(lon, lat), c(lon2, lat2)))
p %>% group_by(1:n()) %>% mutate(dist2prev = distCosine(c(lon, lat), c(lon2, lat2)))

但错误总是一样的:

Wrong length for a vector, should be 2

知道为什么 dplyr 在那里没有成功吗?

【问题讨论】:

  • 按原样为我工作
  • 这也有效:p %&gt;% mutate(dist2prev = distCosine(cbind(lon, lat), cbind(lon2, lat2)))

标签: r dplyr


【解决方案1】:

不确定为什么您的代码无法正常工作。使用 do.call 似乎比您的 vanilla 实现或 dplyr 快几个数量级:

library(geosphere)
library(dplyr)

N <- 100
p <- data.frame(lat=runif(N,-90,90), lon=runif(N,-180,180),
                lat2=runif(N,-90,90), lon2=runif(N,-180,180) )

f1 <- function() {
  sapply(1:nrow(p), function(x) distCosine(c(p$lon[x], p$lat[x]),
                                           c(p$lon2[x], p$lat2[x]) ) )
}

pts <- list(p1=p[2:1], p2=p[4:3])
f2 <- function() {
  do.call(distCosine, pts)
}

f3 <- function() {
  p %>% rowwise() %>% mutate(dist2prev = distCosine(c(lon, lat), c(lon2, lat2)))
}

geosphere::distCosine 的帮助(您没有提到您正在使用哪个库)暗示该函数是矢量化的。这将比进行逐行操作快得多。

> microbenchmark::microbenchmark(vanilla=f1(), do.call=f2(), dplyr=f3())
Unit: microseconds
    expr      min        lq      mean    median         uq       max neval
 vanilla 21342.53 32076.194 39113.213 40463.300 45340.3695 80332.304   100
 do.call   371.34   444.391   617.022   562.337   772.5475  1228.161   100
   dplyr 19800.10 27304.895 35627.085 34618.692 42531.5415 66111.814   100

【讨论】:

    【解决方案2】:

    如果我放弃使用 distCosine 并自己实现该功能,我也会得到快速响应:

    dist <- function(lat1, lon1, lat2, lon2){
      r <- acos(sin(lat1) * sin(lat2) + cos(lat1)*cos(lat2) * cos(abs(lon2-lon1))) * 6378137
    }
    deg2rad <- function(deg) {(deg * pi) / (180)}
    
    p %>% mutate(x = dist(deg2rad(lat1),deg2rad(lon1),deg2rad(lat2),deg2rad(lon2)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-17
      • 1970-01-01
      相关资源
      最近更新 更多