You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:24:53