汇总r中的值时,空间多边形%over%多边形如何工作?


12

我正在进行一个环境流行病学项目,该项目中我有接触点(约2000头工业猪操作-IHO)。这些IHO喷洒在附近的田地上,但粪便中的水滴和气味可能传播数英里。因此,这些点曝光获得了3mi的缓冲区,我想知道每个NC人口普查区块的IHO曝光数量(各种-粪便量,猪的数量之和;最简单的,只是重叠曝光缓冲区的数量) (〜200,000)。排除人口普查区(蓝色)是(1)在人口最多的前5个城市中的任何事物,以及(2)不与县内有IHO接壤的县(注:这是使用gRelate函数和DE-9IM代码完成的-非常光滑!)。见下图可见

在此处输入图片说明

最后一步是将缓冲的曝光量表示汇总到每个人口普查区块。这就是我感到难过的地方。

到目前为止,我在sp程序包中使用%over%函数已经过得很愉快,但是从过分的插图中了解到poly-poly和poly-line over是在rgeos中实现的。该小插图仅涵盖线型多边形和自引用多边形,而不涉及聚合,因此,对于具有函数聚合(例如求和或均值)的多边形的选择,我有些困惑。

对于测试用例,请考虑以下使用世界国家边界文件的冗长代码段。这应该能够被复制出来并按原样运行,因为我为这些点使用了随机种子,并且由于我正在代码中下载和解压缩世界文件。

首先,我们创建100个点,然后将over函数与fn参数一起使用以在数据框中添加元素。这里有很多要点,但请看一下澳大利亚:3分,标号3。到目前为止,一切都很好。

在此处输入图片说明

现在,我们变换几何形状,以便我们可以创建缓冲区,向后变换并映射这些缓冲区。(包括在以前的地图中,因为我仅限于两个链接。)我们想知道每个国家/地区重叠了多少缓冲区-以澳大利亚为例,这是4。虽然要通过over函数来实现。在最后的代码行中看到我的一团糟。

编辑:请注意,关于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,2015年

Answers:


5

感谢您提出的明确问题和可复制的示例。

您的理解是正确的,这归结为rgeos :: over中的一个错误,该错误已在一个月前修复,但尚未纳入CRAN版本。如果您仅对交叉点的数量感兴趣,则可以采用以下解决方法:

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

我在NROW这里使用而不是length这样,以便它与错误的rgeos(来自CRAN的0.3-8)以及已校正的(来自r-forge的0.3-10)一起使用。较早的使用建议

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,2015年

另外,关于最初的问题:我需要计算暴露的次数,但是我也确实需要对它们进行求和-像每次暴露中的生猪数。计算重叠是一个开始……但是听起来我需要的解决方案是引入最新的rgeos,是吗?没有它,没有办法进行功能聚合(不仅仅是计数)吗?
Mike Dolan Fliss,2015年

(1)rgeos ::超过签字SpatialPolygons,SpatialPolygonsDataFrame应返回data.frame,但返回到相同的时索引向量y本来SpatialPolygonssp::aggregate以一种更加用户友好的方式完成您的工作,返回Spatial对象而不是data.frame。CRAN软件包由志愿者维护。
Edzer Pebesma 2015年

好的,谢谢埃德泽。听起来聚合似乎完全依赖rgeos,所以为了使此功能早于CRAN发布周期(无论何时),我将需要了解如何下载最新的rgeos并加以解决。谢谢。感谢您在包装上所做的所有工作!!
Mike Dolan Fliss,2015年

另外,Edzer非常感谢您对R-sis-geo的关注。不确定发布更好的位置在哪里,所以我很高兴该线程现在指向此处。
Mike Dolan Fliss 2015年

1

在此期间,我快速创建了一个快速(且编码不良)的过度替换器,以创建所需的数据帧,因为上述仅计算解决方案或“解决新的rgeos”并不能完全解决我的问题不够熟练,无法理解该怎么做。

该函数显然是(1)不完整的(请注意我如何忽略fn参数)和(2)效率低下,因为在没有R强大的数组操作/ sapply的情况下我来使用它(显然,我来自其他语言而没有这种能力),但老实说,我仍然对over函数的结构返回的结果感到困惑(列表列表...?如果不适用,则为空白列表)。对于它的价值(欢迎编辑),此功能可以成功完成我需要做的工作,并模仿其他功能。

欢迎编辑:

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,2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.