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.