为何st_join(x,y,left=TRUE)返回的sf对象要素数多于输入x?
关于sf包st_join()函数关联多边形属性的问题解答
我有两个包含多个多边形(POLYGON)要素的sf对象,希望通过多边形空间关系将两者的属性关联起来。使用st_join()函数时,默认结果与预期不符,但添加largest = TRUE参数后得到了正确输出,想了解背后的原因。
示例代码
library(sf) library(tidyverse) map1 <- st_as_sfc(c("POLYGON((0 0 , 0 1 , -1 1 , -1 0, 0 0))", "POLYGON((0 0 , 0 2 , 2 2 , 2 0, 0 0 ))", "POLYGON((0 0 , 0 -0.5 , -0.5 -0.5 , -0.5 0, 0 0))")) %>% st_sf(ID = paste0("poly", 1:3), att1 = c(letters[1:3])) map2 <- st_as_sfc(c("POLYGON((0 0 , 0 0.5 , -0.5 .5 , -0.5 0, 0 0))", "POLYGON((-0.5 0 , -0.5 1 , -1 1 , -1 0 , -0.5 0))", "POLYGON((0 0 , 0 1 , 1 1 , 1 0 , 0 0))", "POLYGON((1 1 , 1 2 , 2 2 , 2 1 , 1 1))", "POLYGON((0 0 , 0 -0.25 , -0.25 -0.25 , -0.25 0 , 0 0))")) %>% st_sf(ID = paste0("poly", 4:8)) %>% mutate(att2 = c(LETTERS[1:5])) # 默认调用st_join,结果不符合预期 map3 <- st_join(map2, map1, left = TRUE)
默认结果的问题
默认运行后得到12条要素,而非预期的5条,部分逻辑上不应该关联的多边形也被匹配:
Simple feature collection with 12 features and 4 fields Geometry type: POLYGON Dimension: XY Bounding box: xmin: -1 ymin: -0.25 xmax: 2 ymax: 2 CRS: NA First 10 features: ID.x att2 ID.y att1 . 1 poly4 A poly1 a POLYGON ((0 0, 0 0.5, -0.5 ... 1.1 poly4 A poly2 b POLYGON ((0 0, 0 0.5, -0.5 ... 1.2 poly4 A poly3 c POLYGON ((0 0, 0 0.5, -0.5 ... 2 poly5 B poly1 a POLYGON ((-0.5 0, -0.5 1, -... 2.1 poly5 B poly3 c POLYGON ((-0.5 0, -0.5 1, -... 3 poly6 C poly1 a POLYGON ((0 0, 0 1, 1 1, 1 ... 3.1 poly6 C poly2 b POLYGON ((0 0, 0 1, 1 1, 1 ... 3.2 poly6 C poly3 c POLYGON ((0 0, 0 1, 1 1, 1 ... 4 poly7 D poly2 b POLYGON ((1 1, 1 2, 2 2, 2 ... 5 poly8 E poly1 a POLYGON ((0 0, 0 -0.25, -0....
为什么默认结果不符合预期?
st_join()的默认空间连接规则是**st_intersects(空间交集)**,只要两个几何对象有任何形式的重叠(包括共享顶点、边界线接触),就会生成一条关联记录。
在示例中,map1的三个多边形都共享原点(0,0),而map2的所有多边形都包含这个原点,因此每个map2的多边形都会和map1中所有包含原点的多边形(即全部3个)产生交集匹配,最终导致单条map2要素对应多条map1属性,结果行数远超预期。
为什么largest = TRUE能解决问题?
当设置largest = TRUE时,st_join()会为每个x(这里是map2)要素只匹配与之重叠面积最大的y(这里是map1)要素。这样即使一个x要素和多个y要素有交集,最终也只会保留重叠面积最大的那一组关联,从而保证结果的要素数和x一致(在left = TRUE的前提下)。
另一种解决方案:严格匹配“完全包含”
如果需求是严格判断map2的多边形完全被包含在map1的多边形中,可以指定join = st_within,这样只有满足完全包含关系的要素才会被关联:
map5 <- st_join(map2, map1, left = TRUE, join = st_within)
运行后同样会得到5条要素,符合预期。
内容的提问来源于stack exchange,提问作者baobab
相关产品推荐
相关产品推荐

