在R中自动合并sf数据框或terra SpatVector中的相邻多边形
需求:自动合并相邻多边形
我有一组terra格式的矢量多边形,其中部分多边形相互独立,部分相邻相接。这些相邻多边形原本属于同一形状,但因分年份添加区段等原因被拆分。我需要通过编程自动合并所有相邻多边形(包括连续首尾相接的多个多边形),最终得到行数更少的矢量数据框——比如示例中的7个多边形可合并为4个。
我尝试过用relate()和combineGeoms()手动合并,但大型复杂shapefile需要自动化处理,也接受sf包的解决方案。
最小可复现代码
library(sf) library(dplyr) library(ggplot2) # 定义创建正方形多边形的函数 create_square <- function(x_center, y_center, size) { half_size <- size / 2 st_polygon(list(matrix(c( x_center - half_size, y_center - half_size, x_center + half_size, y_center - half_size, x_center + half_size, y_center + half_size, x_center - half_size, y_center + half_size, x_center - half_size, y_center - half_size ), ncol = 2, byrow = TRUE))) } # 创建单个形状 shape1 <- create_square(1, 1, 1) shape2 <- create_square(4, 1, 1) shape3 <- create_square(6, 1, 1) shape4 <- create_square(7, 1, 1) shape5 <- create_square(7.5, 2, 1) shape6 <- create_square(2.5, 2.5,1) shape7 <- create_square(2, 3.5, 1) # 组合为sf对象 shapes <- st_sf( geometry = st_sfc( shape1, shape2, shape3, shape4, shape5, shape6, shape7 ) ) %>% mutate(name = paste0("shape_",c(1:nrow(.)))) %>% relocate(name) # 设置坐标系(EPSG:4326,WGS84) st_crs(shapes) <- st_crs(4326) # 绘图查看 shapes %>% ggplot() + geom_sf(aes(fill = name)) # 转换为terra的SpatVector格式 library(terra) library(tidyterra) shapes_vect <- vect(shapes) ggplot() + geom_spatvector(data = shapes_vect, aes(fill = name)) # 生成相邻关系矩阵 relate(shapes_vect, shapes_vect, relation = "touches") # 手动合并shape3、4、5 test <- combineGeoms(shapes_vect[3,], shapes_vect[5,]) %>% combineGeoms(shapes_vect[4,]) # 创建合并后的新数据框 shapes_new <- shapes_vect[c(1:2, 6:7),] %>% rbind(test) # 绘制合并后的结果 ggplot() + geom_spatvector(data = shapes_new, aes(fill = name))
自动化解决方案
方案1:使用sf包实现
sf的st_connectivity(sf >= 1.0-0版本可用)可直接计算相邻多边形的连通组件;若版本较低,可结合igraph实现兼容:
方法A:使用st_connectivity(推荐)
library(sf) library(dplyr) # 计算每个多边形的连通组件ID(相邻多边形共享同一ID) shapes <- shapes %>% mutate(connect_id = st_connectivity(geometry, relation = "touches")) # 按连通组件分组合并多边形 merged_shapes_sf <- shapes %>% group_by(connect_id) %>% summarise( merged_names = paste(name, collapse = ", "), geometry = st_union(geometry) ) %>% ungroup() # 可视化结果 merged_shapes_sf %>% ggplot() + geom_sf(aes(fill = factor(connect_id))) + labs(title = "sf包合并后的相邻多边形", fill = "组件ID")
方法B:sf + igraph(兼容旧版本)
library(sf) library(dplyr) library(igraph) # 生成多边形相邻关系图 touch_graph <- st_touches(shapes, shapes) %>% graph_from_adj_list(mode = "undirected") # 获取连通组件ID connect_id <- components(touch_graph)$membership # 按组件ID合并多边形 shapes <- shapes %>% mutate(connect_id = connect_id) merged_shapes_sf <- shapes %>% group_by(connect_id) %>% summarise( merged_names = paste(name, collapse = ", "), geometry = st_union(geometry) ) %>% ungroup()
方案2:使用terra包实现
terra的patches()函数可直接识别相邻多边形组,再通过aggregate()完成合并:
library(terra) library(tidyterra) # 识别相邻多边形的分组ID shapes_vect$patch_id <- patches(shapes_vect, relation = "touches") # 按分组ID合并多边形,保留原名称信息 merged_shapes_terra <- aggregate(shapes_vect, by = "patch_id", fun = function(x) paste(x, collapse = ", ")) # 可视化结果 ggplot() + geom_spatvector(data = merged_shapes_terra, aes(fill = factor(patch_id))) + labs(title = "terra包合并后的相邻多边形", fill = "分组ID")
两种方案均可自动识别所有相邻多边形组并合并,示例中的7个多边形会被合并为4个独立组:shape1单独一组、shape2单独一组、shape3/4/5为一组、shape6/7为一组。
内容的提问来源于stack exchange,提问作者Jake L
相关产品推荐
相关产品推荐

