r에서 값을 집계 할 때 공간 폴리곤 % over % 폴리곤은 어떻게 작동합니까?


12

나는 포인트 노출 (~ 2,000 산업 호그 작업-IHO)이있는 환경 역학 프로젝트를 진행하고 있습니다. 이 IHO는 근처 필드에 뿌려 지지만 대변 물방울과 냄새는 수 마일을 여행 할 수 있습니다. 따라서 이러한 점 노출은 3mi 버퍼를 얻습니다. 나는 NC 인구 조사 블록 당 IHO 노출 수 (다양한 종류-분뇨의 양, 호그 수, 가장 단순한, 겹치는 노출 버퍼 수)를 알고 싶습니다. (~ 200,000). 제외 인구 조사 블록 (파란색)은 (1) 가장 인구가 많은 상위 5 개 도시의 도시 및 (2) IHO와 카운티를 경계로하지 않는 카운티 (참고 : gRelate 함수 및 DE-9IM 코드로 수행됨- 매우 매끄러운!). 비주얼은 아래 이미지를 참조하십시오

여기에 이미지 설명을 입력하십시오

마지막 단계는 버퍼링 된 노출 표현을 모든 센서스 블록으로 집계하는 것입니다. 내가 여기에 끼인 곳입니다.

지금까지 sp 패키지의 % over % 함수를 사용하여 좋은 시간을 보냈지 만 rpolys에서 poly-poly 및 poly-line over가 구현되어 있음을 오버 비네팅에서 이해할 수 있습니다. 비네팅은 선 폴리 및 자체 참조 폴리에만 적용되며 집계에는 포함되지 않으므로 합계 또는 평균과 같은 함수 집계와 함께 폴리 폴리에 대한 옵션이 무엇인지 약간 혼동됩니다.

테스트 사례의 경우 세계 국가 테두리 파일로 작업하는 아래의 다소 자세한 스 니펫을 고려하십시오. 포인트에 임의의 시드를 사용하고 코드에서 월드 파일을 다운로드하고 압축을 풀기 때문에 이것은 그대로 복사하고 실행할 수 있어야합니다.

먼저 100 점을 만든 다음 fn 인수와 함께 over 함수를 사용하여 데이터 프레임에 요소를 추가합니다. 여기에는 많은 포인트가 있지만 호주를 살펴보십시오 : 3 포인트, 3 번 레이블. 여태까지는 그런대로 잘됐다.

여기에 이미지 설명을 입력하십시오

이제 지오메트리를 변환하여 버퍼를 생성하고 다시 변환하고 버퍼를 매핑 할 수 있습니다. (두 개의 링크로 제한되어 있기 때문에 이전지도에 포함되어 있습니다.) 우리는 각 나라가 얼마나 많은 버퍼를 겹치는 지 알고 싶습니다. 호주의 경우 눈으로는 4입니다. 오버 기능으로 그것을 얻을 수 있습니다. 마지막 코드 줄에서 시도의 혼란을 보라.

편집 : r-sis-geo의 주석자가 스택 교환 질문 63577에서 참조 된 집계 함수를 언급 했으므로 해결 방법 / 흐름이 해당 기능을 통해 이루어질 수 있지만 왜 갈 필요가 있는지 이해하지 못합니다. 다 공간에 대한 집계는 다른 공간 객체에 대해 그 기능을 갖는 것 같습니다.

require(maptools)
require(sp)
require(rgdal)
require(rgeos)

download.file("http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip", destfile="world.zip")
unzip("world.zip")
world.map = readOGR(dsn=".", "TM_WORLD_BORDERS_SIMPL-0.3", stringsAsFactors = F)
orig.world.map = world.map #hold the object, since I'm going to mess with it.

#Let's create 500 random lat/long points with a single value in the data frame: the number 1
set.seed(1)
n=100
lat.v = runif(n, -90, 90)
lon.v = runif(n, -180, 180)
coords.df = data.frame(lon.v, lat.v)
val.v = data.frame(rep(1,n))
names(val.v) = c("val")
names(coords.df) = c("lon", "lat")
points.spdf = SpatialPointsDataFrame(coords=coords.df, proj4string=CRS("+proj=longlat +datum=WGS84"), data=val.v)
points.spdf = spTransform(points.spdf, CRS(proj4string(world.map)))
plot(world.map, main="World map and points") #replot the map
plot(points.spdf, col="red", pch=20, cex=1, add=T) #...and add points.

#Let's use over with the point data
join.df = over(geometry(world.map), points.spdf,  fn=sum)
plot(world.map, main="World with sum of points, 750mi buffers") #Note - happens to be the count of points, but only b/c val=1.
plot(points.spdf, col="red", pch=20, cex=1, add=T) #...and add points.
world.map@data = data.frame(c(world.map@data, join.df))
#world.map@data = data.frame(c(world.map@data, over(world.map, points.spdf, fun="sum")))
invisible(text(getSpPPolygonsLabptSlots(world.map), labels=as.character(world.map$val), cex=1))
#Note I don't love making labels like above, and am open to better ways... plus I think it's deprecated/ing

#Now buffer...
pointbuff.spdf = gBuffer(spTransform(points.spdf, CRS("+init=EPSG:3358")), width=c(750*1609.344), byid=T)
pointbuff.spdf = spTransform(pointbuff.spdf, world.map@proj4string)
plot(pointbuff.spdf, col=NA, border="pink", add=T)



#Now over with the buffer (poly %over% poly).  How do I do this?
world.map = orig.world.map
join.df = data.frame(unname(over(geometry(world.map), pointbuff.spdf, fn=sum, returnList = F)) ) #Seems I need to unname this...?
names(join.df) = c("val")
world.map@data = data.frame(c(world.map@data, join.df)) #If I don't mess with the join.df, world.map's df is a mess..
plot(world.map, main="World map, points, buffers...and a mess of wrong counts") #replot the map
plot(points.spdf, col="red", pch=20, cex=1, add=T) #...and add points.
plot(pointbuff.spdf, col=NA, border="pink", add=T)
invisible(text(getSpPPolygonsLabptSlots(world.map), labels=as.character(world.map$val), cex=1)) 
#^ But if I do strip it of labels, it seems to be misassigning the results?
# Australia should now show 4 instead of 3.  I'm obviously super confused, probably about the structure of over poly-poly returns.  Help?

리디렉션을 감사합니다. 여기서 삭제하고 다시 게시해야하나요? 가장 좋은 움직임은 무엇입니까? 감사.
Mike Dolan Fliss

답변:


5

명확한 질문과 재현 가능한 예에 감사드립니다.

당신의 이해는 정확하며 rgeos :: over의 버그로 귀결됩니다. rgeos :: over는 한 달 전에 수정 되었지만 아직 CRAN 릴리스로 만들지 않았습니다. 다음은 교차 횟수에만 관심이있는 경우 해결 방법입니다.

world.map$val = sapply(over(geometry(world.map), pointbuff.spdf, returnList = TRUE), NROW)

나는 올바른 rgeos (0.3-8, CRAN에서)뿐만 아니라 수정 된 (0.3-10, r-forge에서) 작동하도록 NROW대신 여기를 사용하고 있습니다 length. 사용의 초기 제안

a = aggregate(pointbuff.spdf, world.map, sum)

또한 교차 수를 계산하지만 고정 rgeos 버전 만 설치되어 있습니다. 보다 직관적 인 이름 외에도 장점은 Spatial의 지오메트리로 객체를 직접 반환한다는 것 입니다 world.map.

rgeos 0.3-8을 작동 시키려면

setMethod("over",
    signature(x = "SpatialPolygons", y = "SpatialPolygonsDataFrame"),
        rgeos:::overGeomGeomDF)

를 사용하기 전에 스크립트에 추가하십시오 over.


매우 도움이됩니다. 감사합니다. 특히 수정 전 / 후에 작동하는 솔루션을 제공하고 싶습니다. (1) 내가 여기서 겪고있는 버그는 무엇입니까? rgeos :: over는 공간 폴리 데이터 프레임이 아닌 공간 폴리곤 지리를 반환합니까? 함수 중 일부는 데이터 프레임 만 반환하지 않습니까? (2) 이것이 일반적으로 집계 이상에서 어떻게 작동합니까? 의도 된 차이점과 사용 사례에 대해 약간 혼란 스럽습니다. 정말 당신의 무게를 주셔서 감사합니다, 감사합니다. 그리고 참고 사항 : CRAN 릴리스주기를 이해하기위한 제안 사항이 있습니까?
Mike Dolan Fliss

또한 원래 질문에 관해서는 : 노출 수를 계산해야하지만 각 노출의 호그 수와 같은 것들을 합산해야합니다. 중복 계산은 시작이지만 ... 필요한 해결책은 최신 rgeo를 가져 오는 것 같습니다. 그것없이 기능 집계를 수행 할 수있는 방법이 없습니까?
Mike Dolan Fliss

(1) rgeos :: 이상 서명은 SpatialPolygons,SpatialPolygonsDataFrame를 반환해야 data.frame하지만, 경우에 동일한 인덱스 벡터를 반환 y했을 것이다을 SpatialPolygons. sp::aggregate보다 사용자 친화적 인 방식으로 작업을 수행하여 Spatial대신 객체를 반환 합니다 data.frame. CRAN 패키지는 자원 봉사자가 관리합니다.
Edzer Pebesma

고마워요 Edzer. 집계가 rgeos에 의존하는 것처럼 들리므로 CRAN 릴리스주기보다 앞서이 기능을 사용하려면 (그때마다) 최신 rgeo를 다운로드하고 해결하는 방법을 찾아야합니다. 감사합니다. 그리고 패키지에 대한 모든 작업에 감사드립니다 !!
Mike Dolan Fliss

또한 Edzer는 R-sis-geo에 대한 참고에 감사드립니다. 게시하기 더 좋은 곳이 어디인지 확실하지 않았으므로 스레드가 여기에 있음을 기쁘게 생각합니다.
Mike Dolan Fliss

1

위의 계산 전용 솔루션이나 "새로운 rgeos에서 작업"으로 내 질문에 대답하지 않기 때문에 필요한 데이터 프레임을 만드는 빠른 (그리고 잘못 코딩 된) 오버 교체기를 채찍질했습니다. 어떻게해야할지 충분히 이해하지 못했습니다.

이 함수는 분명히 (1) 불완전합니다 (fn 인수를 무시하는 방법에 유의하십시오) 및 (2) 비효율적입니다 .R의 강력한 배열 조작 / sapply없이오고 있기 때문에 ... 그 힘) 그러나 솔직히, 나는 여전히 오버 함수의 구조가 무엇을 반환하는지 (리스트 목록 ...? 그리고 빈 목록이라면 NA?) 혼란 스럽습니다. 가치있는 일을 위해 (편집을 환영합니다)이 기능은 필요한 작업을 성공적으로 수행하며 다른 기능에 대한 다른 작업을 모방합니다.

환영합니다 :

overhelper <- function(pol, pol.df, fn=sum, verbose=F){
   if(verbose) {cat("Building over geometry...\n"); t=Sys.time(); t}
   geolist = over(geometry(pol), pol.df, returnList = T)
   if(verbose) {cat("Geometry done. Aggregating df. \n"); Sys.time()-t;t=Sys.time();t;}
   results = data.frame(matrix(0,nrow=length(pol), ncol=ncol(pol.df)))
   names(results) = names(pol.df)
   end = length(geolist)

   for (i in 1:end){
     if(verbose) cat(i, "...")
     results[i,] = sapply(pol.df@data[unlist(geolist[i]),], fn)
   }
   if(verbose) cat("Aggregation done! (", Sys.time()-t, ") \n Returning result vector.")
   return (results)
}

1
rgeos 0.3-8을 고정시키는 대안을 내 대답에 추가했습니다.
Edzer Pebesma
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.