簡體   English   中英

如何使用doParallel計算R中zipcodes之間的距離?

[英]How to use doParallel for calculating distance between zipcodes in R?

我有一個大型數據集(2.6M行),有兩個郵政編碼和相應的緯度和經度,我正在嘗試計算它們之間的距離。 我主要使用包geosphere來計算郵政編碼之間的Vincenty Ellipsoid距離,但是我的數據集耗費了大量時間。 有什么可以快速實現這個?

我嘗試了什么

library(tidyverse)
library(geosphere)

zipdata <- select(fulldata,originlat,originlong,destlat,destlong)

## Very basic approach
for(i in seq_len(nrow(zipdata))){
  zipdata$dist1[i] <- distm(c(zipdata$originlat[i],zipdata$originlong[i]),
       c(zipdata$destlat[i],zipdata$destlong[i]),
       fun=distVincentyEllipsoid)
}

## Tidyverse approach 
zipdata <- zipdata%>%
 mutate(dist2 = distm(cbind(originlat,originlong), cbind(destlat,destlong), 
   fun = distHaversine))

這兩種方法都非常慢。 我知道2.1M行永遠不會是一個“快速”計算,但我認為它可以更快。 我已經嘗試了以下方法對較小的測試數據沒有任何運氣,

library(doParallel)
cores <- 15
cl <- makeCluster(cores)
registerDoParallel(cl)

test <- select(head(fulldata,n=1000),originlat,originlong,destlat,destlong)

foreach(i = seq_len(nrow(test))) %dopar% {
  library(geosphere)
  zipdata$dist1[i] <- distm(c(zipdata$originlat[i],zipdata$originlong[i]),
       c(zipdata$destlat[i],zipdata$destlong[i]),
       fun=distVincentyEllipsoid) 
}
stopCluster(cl)

誰能幫我出既可以正確的使用方法doParallelgeosphere或更好的方式來處理這個問題?

編輯:(部分)回復的基准

## benchmark
library(microbenchmark)
zipsamp <- sample_n(zip,size=1000000)
microbenchmark(
  dave = {
    # Dave2e
    zipsamp$dist1 <- distHaversine(cbind(zipsamp$patlong,zipsamp$patlat),
                                   cbind(zipsamp$faclong,zipsamp$faclat))
  },
  geohav = {
    zipsamp$dist2 <- geodist(cbind(long=zipsamp$patlong,lat=zipsamp$patlat),
                             cbind(long=zipsamp$faclong,lat=zipsamp$faclat),
                             paired = T,measure = "haversine")
  },
  geovin = {
    zipsamp$dist3 <- geodist(cbind(long=zipsamp$patlong,lat=zipsamp$patlat),
                             cbind(long=zipsamp$faclong,lat=zipsamp$faclat),
                             paired = T,measure = "vincenty")
  },
  geocheap = {
    zipsamp$dist4 <- geodist(cbind(long=zipsamp$patlong,lat=zipsamp$patlat),
                             cbind(long=zipsamp$faclong,lat=zipsamp$faclat),
                             paired = T,measure = "cheap")
  }
,unit = "s",times = 100)

# Unit: seconds
# expr        min         lq       mean     median         uq        max neval  cld
# dave 0.28289613 0.32010753 0.36724810 0.32407858 0.32991396 2.52930556   100    d
# geohav 0.15820531 0.17053853 0.18271300 0.17307864 0.17531687 1.14478521   100  b  
# geovin 0.23401878 0.24261274 0.26612401 0.24572869 0.24800670 1.26936889   100   c 
# geocheap 0.01910599 0.03094614 0.03142404 0.03126502 0.03203542 0.03607961   100 a  

一個簡單的all.equal測試表明,對於我的數據集,hasrsine方法等於vincenty方法,但是與geodist包中的“廉價”方法具有“平均相對差異:0.01002573”。

R是矢量化語言,因此該函數將對矢量中的所有元素進行操作。 由於您要計算每行的原始距離和目標距離,因此不需要循環。 矢量化方法大約是循環性能的1000倍。
另外直接使用distVincentyEllipsoid (或distHaveersine等)並繞過distm函數也應該提高性能。

沒有任何樣本數據,此代碼段未經測試。

library(geosphere)

zipdata <- select(fulldata,originlat,originlong,destlat,destlong)

## Very basic approach
zipdata$dist1 <- distVincentyEllipsoid(c(zipdata$originlong, zipdata$originlat), 
       c(zipdata$destlong, zipdata$destlat))

注意: 為了使大多數地圈功能正常工作,正確的順序是:經度首先是緯度。

上面列出的整擺方法很慢的原因是, distm函數計算每個起點和目的地之間的距離,這將導致200 distm 200萬個元素矩陣。

如果你打算使用geosphere,我會使用像distHaversine這樣的快速近似方法,或者使用仍然快速且非常精確的distGeo方法。 (distVincenty *這些主要是為了好奇而實施的)。

我使用@ SymbolixAU的建議來使用geodist包來對我的數據集執行2.1M距離計算。 我發現每次測試都比geosphere包快得多(我在主要問題中添加了其中一個)。 geodistmeasure=cheap選項使用廉價的標尺方法,該方法在100kms的距離以下具有低錯誤率。 有關詳細信息,請參閱geodist vignette 鑒於我的一些距離高於100公里,我決定使用Vincenty Ellipsoid測量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM