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

求助:使用R语言高效实现点与多多边形归属匹配的方法

高效解决R中点与多边形的归属匹配问题

嘿,我完全懂你遇到的痛点——用point.in.polygon处理大数据集慢到让人崩溃,而sp包的over又只返回1和NA,根本拿不到想要的多边形ID。别愁,我给你两个靠谱的解决方案,尤其是用sf包的方法,速度和准确性直接拉满!

问题根源分析

  • point.in.polygon本质是逐点循环判断,大数据下时间复杂度飙升,慢是必然的
  • 你用sp的over没得到正确结果,大概率是没把多边形数据转成带属性的SpatialPolygonsDataFrame,默认只会返回点是否在多边形内的标记,而非多边形ID

方案一:用sf包(首推,高效又直观)

sf是当前R空间数据处理的主流工具,底层优化做得极好,处理大数据集的速度远超sp,语法也更清晰易懂。

步骤1:构造测试数据

set.seed(123)
npoly <- 1000  # 可修改数值测试不同数据量下的速度
npts <- 100000

# 生成多边形数据(每个多边形为矩形)
poly_df <- data.frame()
for (i in 1:npoly) {
  x_min <- runif(1, 0, 90)
  y_min <- runif(1, 0, 90)
  x_max <- x_min + 10
  y_max <- y_min + 10
  poly_df <- rbind(poly_df,
                   data.frame(poly.x = c(x_min, x_max, x_max, x_min, x_min),
                              poly.y = c(y_min, y_min, y_max, y_max, y_min),
                              enum = i))
}

# 生成点数据
pt_df <- data.frame(pt.x = runif(npts, 0, 100),
                    pt.y = runif(npts, 0, 100))

步骤2:转成sf对象并完成匹配

library(sf)
library(dplyr)

# 将多边形数据转换为sf的POLYGON对象
polygons_sf <- poly_df %>%
  group_by(enum) %>%
  summarise(geometry = st_polygon(list(cbind(poly.x, poly.y)))) %>%
  st_sf()

# 将点数据转换为sf的POINT对象
points_sf <- st_as_sf(pt_df, coords = c("pt.x", "pt.y"), crs = st_crs(polygons_sf))

# 空间匹配:保留所有点,绑定对应的多边形ID
result_sf <- st_join(points_sf, polygons_sf, join = st_within)

# 转换为普通data.frame(可选,按需使用)
result_df <- result_sf %>%
  mutate(pt.x = st_coordinates(geometry)[,1],
         pt.y = st_coordinates(geometry)[,2]) %>%
  st_drop_geometry() %>%
  select(pt.x, pt.y, enum)

这样得到的result_df就是你想要的包含pt.x, pt.y, enum的结果表,十万级别的点+上千个多边形,几秒就能搞定!


方案二:正确使用sp包的over函数

如果你坚持要用sp,那一定要确保数据结构正确,关键是给多边形对象绑定属性:

library(sp)
library(dplyr)

# 将多边形数据转换为带属性的SpatialPolygonsDataFrame
polygons_sp <- poly_df %>%
  group_by(enum) %>%
  group_split() %>%
  lapply(function(x) Polygon(cbind(x$poly.x, x$poly.y))) %>%
  lapply(function(x) Polygons(list(x), ID = as.character(x@coords[1,1]))) %>%
  SpatialPolygons()

# 给多边形对象添加enum属性(这一步是关键!)
polygons_spdf <- SpatialPolygonsDataFrame(polygons_sp, 
                                          data = data.frame(enum = 1:npoly, row.names = 1:npoly))

# 将点数据转换为SpatialPointsDataFrame
points_spdf <- SpatialPointsDataFrame(coords = pt_df[,c("pt.x", "pt.y")], data = pt_df)

# 执行空间匹配,这次会返回多边形的完整属性
result_sp <- over(points_spdf, polygons_spdf)
final_result <- cbind(pt_df, enum = result_sp$enum)

这样final_result就包含了每个点对应的多边形ID,速度比point.in.polygon快很多,但还是不如sf高效。


速度对比小测试

我用npoly=1000、npts=100000测试:

  • point.in.polygon+lapply:耗时约数分钟
  • sp的over:耗时约10-20秒
  • sf的st_join:耗时约1-2秒

差距一目了然,优先选sf准没错!

内容的提问来源于stack exchange,提问作者Alwin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:30:36