使用distCosine计算距离

时间:2017-03-30 15:13:32

标签: r dplyr

我想计算(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在那里没有成功?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

如果我放弃使用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)))