2014-12-19 4 views
7

저는 약 1000 명의 사람들을위한 많은 위치를 가지고 있습니다. 전체 데이터 세트는 약 250 만 개 였고 처리 스크립트는 실행하는데 약 20 시간이 걸렸습니다. 그러나 지금은 2400 만 회의 관측과 코드 정리 작업과 가능한 경우 병렬 처리 작업을 사용해야합니다.병렬 처리 및/또는 plyr/dplyr를 사용하여 gDistance 기능의 속도/사용을 향상 시키시겠습니까?

각 점에 대해 가장 가까운 다각형 (대부분의 점은 다각형에 없음) 및 해당 다각형의 거리를 찾고 싶습니다. 이 포인트는 주로 바다에서 관측되며 폴리곤은 가장 가까운 해안 (미국) 카운티입니다.

저는 rgeos 패키지의 gDistance 기능을 사용하여이 작업을 수행해 왔으며 각 개인이 처리를 중단하기 위해 일련의 루프를 실행하고 있습니다 (알고 있습니다). 나는 이것을 plyr/dplyr 구문으로 어떻게 움직이는지를 알아 내려고 많은 시간을 보냈지 만 그것을 얻을 수는 없다. 내 문제의 일부로, SpatialPoint 및 SpatialPoylgonDataFrames 인 객체 클래스와 관련 있다고 가정합니다.

library(sp) 
library(rgeos) 
library(plyr) 
# Create SpatialPointsDataFrame 
# My actual dataset has 24 million observations 
my.pts <- data.frame(LONGITUDE=c(-85.4,-84.7,-82.7,-82.7,-86.5,-88.9,-94.8,-83.9,-87.8,-82.8), 
      LATITUDE=c(30.0,29.9,27.5,28.5,30.4,26.1,29.3,28.0,29.4,27.8), 
      MYID=c(1,1,2,2,2,2,3,4,4,4), 
      INDEX=1:10) 
coordinates(my.pts) <- c("LONGITUDE","LATITUDE") 

# Create two polygons in a SpatialPolygonsDataFrame 
# My actual dataset has 71 polygons (U.S. counties) 
x1 <- data.frame(x=c(-92.3, -92.3, -90.7, -90.7, -92.3, -92.3),y=c(27.6, 29.4, 29.4, 27.6, 27.6, 27.6)) 
x1 <- as.data.frame(x1) 
x1 <- Polygon(rbind(x1,x1[1,])) 

x2 <- data.frame(x=c(-85.2, -85.2, -83.3, -83.2, -85.2, -85.2),y=c(26.4, 26.9, 26.9, 26.0, 26.4,  26.4)) 
x2 <- as.data.frame(x2) 
x2 <- Polygon(rbind(x2,x2[1,])) 

poly1 <- Polygons(list(x1),"poly1") 
poly2 <- Polygons(list(x2),"poly2") 
myShp <- SpatialPolygons(list(poly1,poly2),1:2) 
sdf <- data.frame(ID=c(1,2)) 
row.names(sdf) <- c("poly1","poly2") 
myShp <- SpatialPolygonsDataFrame(myShp,data=sdf) 

    # I have been outputting my results to a list. With this small sample, it's easy to just put everything into the object county.vec. But I worry that the 24 million x 71 object would not be feasible. The non-loop version shows the output I've been getting more easily. 

    COUNTY.LIST <- list() 
    county.vec <- gDistance(my.pts, myShp, byid=TRUE) 
    COUNTY.LIST[[1]] = apply(county.vec, 2, min) 
    COUNTY.LIST[[2]] = apply(county.vec, 2, which.min) 
    COUNTY.LIST[[3]] = my.pts$INDEX 

# I have been putting it into a loop so that county.vec gets dumped for each version of the loop. 
# Seems like this could be done using dlply perhaps? And then I would have the power of parallel processing? 
idx <- unique(my.pts$MYID) 
COUNTY.LIST <- list() 
for(i in 1:length(idx)){ 
    COUNTY.LIST[[i]] <- list() 
    county.vec <- gDistance(my.pts[my.pts$MYID==idx[i],], myShp, byid=TRUE) 
    COUNTY.LIST[[i]][[1]] = apply(county.vec, 2, min) 
    COUNTY.LIST[[i]][[2]] = apply(county.vec, 2, which.min) 
    COUNTY.LIST[[i]][[3]] = my.pts$MY[my.pts$MYID==idx[i]] 
    rm(county.vec) 
} 

dlply(my.pts,.(MYID),gDistance(my.pts, myShp, byid=TRUE),.parallel=TRUE) 
> dlply(my.pts,.(MYID),gDistance(my.pts, myShp, byid=TRUE)) 
Error in eval.quoted(.variables, data) : 
envir must be either NULL, a list, or an environment. 

# I suspect this error is because my.pts is a SpatialPointsPolygon. I also recognize that my function call probably isn't right, but first things first. 

# I tried another way to reference the MYID field, more inline with treatment of S4 objects... 
dlply(my.pts,[email protected]$MYID,gDistance(my.pts, myShp, byid=TRUE),.parallel=TRUE) 

# It yields the same error. 

사람들이 가지고있는 제안에 감사드립니다.

+0

'dlply()'는 SpatialPointsDataFrame을 처리 할 수 ​​있습니까? 나는 모른다. – Steven

+1

나는 그렇게 할 수는 없다고 생각하지만, 나는 그런 주장을하기에 떨고있다! 사람들은 항상 똑똑한 반응을 보였지만, 해결 방법이 있거나 놀라 울 정도로 적절한 방법이 있다면 놀라지 않을 것입니다. – Jordan

답변

8

이것은 오래된 질문이지만 내 간단한 방법으로 다른 사람들을 도울 수 있습니다.
평행선을 사용하고 있습니다. 저는 일반적인 예를 쓰고 있습니다. 이전 데이터 질문을 실행하지 않습니다.

set.seed(1) 
#Create the clusters 
library(doParallel) 
cl <- makeCluster(detectCores()) 
registerDoParallel(cl) 
#Export the environment variables to each cluster 
clusterExport(cl,ls()) 
#Load the library "rgeos" to each cluster 
clusterEvalQ(cl, library(rgeos)) 
#Split the data 
ID.Split<-clusterSplit(cl,unique(poly1$ID)) 
#Define a function that calculates the distance of one ID in relation to the poly2 
a<-function(x) gDistance(spgeom1 = poly1[x,], spgeom2 = poly2, byid=TRUE) 
#Run the function in each cluster 
system.time(m<-clusterApply(cl, x=ID.Split, fun=a)) 
#Cluster close 
stopCluster(cl) 
#Merge the results 
output<- do.call("cbind", m) 

이 정보가 도움이되기를 바랍니다.

+0

이 기능을 사용 하시겠습니까? – Seymour

+0

checkForRemoteErrors (val)의 오류 : 노드 8 개가 오류를 생성했습니다. 첫 번째 오류 : 'poly1'객체를 찾을 수 없습니다. – Seymour

+0

'poly1'와'poly2'는 거리를 계산하려는 두 개의 다각형입니다. 변수 이름을 자신의 것으로 대체 하시겠습니까? – juanbretti