R sf:多边形列表上的st_intersection

问题描述

我有一个名为p_1,p_2,...,p_n的多边形(和多多边形)列表。我想获得它们全部相交的区域。由于st_intersection()不接受列表作为参数,因此我尝试了以下三种方法。他们都没有提供令人满意的解决方案,这就是为什么我在寻找替代的,更有效的技术。

(i)我可以遍历列表

for(i in P) p_1 <- st_intersection(p_1,i)

其中P是包含多边形p_2至p_n的列表。但这很慢。

(ii)一种do.call()方法,即

p <- do.call(st_intersection,P)

其中P是多边形p_1到p_n的列表,仅计算列表中前两个多边形之间的交点。

(iii)我可以将多边形组合成一个sf对象,然后运行st_intersection()

p <- do.call(c,P) %>% 
   st_sf() %>% 
   st_intersection()

它有效,但是速度很慢。大概是因为除了P中所有多边形的公共交点之外,它还衍生出许多其他多边形。

三种方法均不能提供令人满意的解决方案。在并行化框架中遍历成对比较的层次结构可能会更快。但是,我认为有比这更简单,更有效的解决方案。

欢迎任何评论和建议。

给昨天关闭此问题的人的注释:不要关闭此问题。如果您个人有问题,请评论或给我发私人消息。但是不要关闭它。

解决方法

我不认为遍历列表的开销在这里是个问题:找到多个多边形的交集只是计算上的昂贵。但是,使用do.call可以轻松地管理将函数顺序应用于列表成员的方法(实际上是您尝试对purrr::accumulate进行的操作):

您在这里没有可重现的示例,以供人们测试可能的解决方案,并且从头开始创建sf多边形涉及一些工作,因此可能就是为什么您上一个问题已被关闭-我不知道不知道。

无论如何,让我们在列表中创建三个重叠的正方形并绘制它们:

library(sf)
library(purrr)

# create square
s1 <- rbind(c(1,1),c(10,10),c(1,1))
p  <- list(s1 = s1,s2 = s1 + 4,s3 = s1 - 4)
p  <-  lapply(p,function(x) st_sfc(st_polygon(list(x))) )

plot(p[[1]],xlim = c(-5,15),ylim = c(-5,15))
plot(p[[2]],add = TRUE)
plot(p[[3]],add = TRUE)

enter image description here

我们的目标是找到所有三个正方形的交点,这当然是中心的小正方形。使用purrr,这很容易:

intersection <- accumulate(p,st_intersection)$s3

因此,当我们将结果添加为红色时,我们得到:

plot(intersection,col = "red",add = TRUE)

enter image description here

在性能方面,accumulate仅比原始循环快10%,因此,如果性能是一个大问题,则可能需要并行处理。另外,如果所有多边形之间都没有交集,则可以找到最小的多边形,并使用st_intersects以确保所有多边形实际相交。只要有相当大的机会不存在非交叉点,这是一个更快的计算。