空间对象版rbindlist?批量合并SpatialPolygonDataFrames性能优化求助
解决大量SpatialPolygonDataFrames合并慢的问题
嘿,我完全懂你这种头疼的感觉——15000个空间对象循环用rbind()合并,越到后面速度越慢,简直是效率杀手!确实,rbindlist没法直接处理S4类型的sp对象,但咱们有几个更高效的方案:
方案1:切换到sf包(最推荐,长期收益高)
现在空间数据处理的主流是sf包,它的对象本质是带几何列的普通数据框,完美兼容dplyr或data.table的高效合并工具,而且整体性能比sp好太多。
把你的代码改成sf版本试试:
library(sf) # 把SpatialLinesDataFrame转成sf对象 roads_sf <- st_as_sf(roads) # 批量生成每个道路的缓冲差集,再合并 difference_sf <- lapply(1:nrow(roads_sf), function(i) { # 生成两个缓冲 buf_15 <- st_buffer(roads_sf[i,], dist = 15, endCapStyle = "ROUND") buf_10 <- st_buffer(roads_sf[i,], dist = 10, endCapStyle = "ROUND") # 计算差集 diff_poly <- st_difference(buf_15, buf_10) # 设置ID(和你原来的逻辑一致) diff_poly$oid <- roads_sf[i,]$oid diff_poly }) %>% # 用dplyr的bind_rows或者data.table的rbindlist都可以,后者更快 data.table::rbindlist() # 如果需要转回sp对象(可选) difference_sp <- as(difference_sf, "Spatial")
sf的向量化操作和内存管理比sp高效得多,15000个对象的合并速度会提升一大截。
方案2:优化sp对象的合并逻辑(不换包的临时方案)
如果你暂时不想切换到sf,那别再每次循环都rbind()了——每次rbind()都会复制整个已有的difference对象,内存开销随循环次数暴增。改成先把所有临时对象存进列表,最后一次性合并:
# 初始化空列表存所有临时多边形 diff_list <- vector("list", nrow(roads)) for (i in 1:nrow(roads)) { temp <- gDifference(gBuffer(roads[i,], byid = TRUE, width = 15, capStyle = 'ROUND'), gBuffer(roads[i,], byid = TRUE, width = 10, capStyle = 'ROUND')) slot(slot(temp, "polygons")[[1]], "ID") <- as.character(roads[i,]$oid) diff_list[[i]] <- temp rm(temp) print(i) } # 一次性合并列表里的所有对象 difference <- do.call(rbind, diff_list)
这个改动能避免循环中反复复制大对象,速度会比原来的循环rbind快很多。
补充:为什么rbindlist不能处理sp对象?
没错,rbindlist是为普通数据框/ data.table设计的,而sp对象是S4类的复杂结构,包含多边形、投影、数据框等多个槽位,rbindlist没法识别这些结构,所以没法直接用。而sf对象本质是继承自data.frame的,所以可以完美兼容这类工具。
内容的提问来源于stack exchange,提问作者TheRealJimShady
相关产品推荐
相关产品推荐

