替换sf特定点几何图形失败的问题及解决方案咨询
解决sf几何列更新的问题(基于dplyr的最优方案)
你的问题核心是在使用tidyverse风格更新sf几何列时,没处理好几何对象的类型匹配和重复行的长度匹配。我来帮你拆解错误原因,并给出最优的解决方案:
错误原因分析
- 方法1(case_when)失败:你返回的是
st_sfc(st_point(...))(一个包含单个点的sfc对象),但原几何列的每个元素是单个sfg对象(比如st_point),同时当a==17时有2行,你只返回了1个sfc元素,导致长度和类型双重不匹配,触发错误。 - 方法2(基础赋值)失败:当a==17时有2行,但你只给了1个sfc元素,
st_geometry<-要求赋值的sfc长度必须与选中的行数一致。
推荐解决方案(基于dplyr::case_when)
这是最符合你tidyverse使用习惯的写法,保证类型和长度都匹配:
sf2 <- sf %>% mutate(geometry = st_sfc( case_when( # 对每个符合条件的行,返回单个st_point(sfg),用list包裹确保长度匹配 a == 17 ~ list(st_point(c(12, 13))), a == 16 ~ list(st_point(c(5, 6))), # 其他行返回原几何的单个元素 TRUE ~ as.list(geometry) ), # 保留原数据的坐标参考系(非常重要,避免丢失CRS信息) crs = st_crs(sf) ))
另一种tidyverse风格写法(用purrr::map)
如果你的条件逻辑更复杂,用purrr::map逐行处理会更灵活:
library(purrr) sf2 <- sf %>% mutate(geometry = map2(a, geometry, ~{ if (.x == 17) st_point(c(12, 13)) else if (.x == 16) st_point(c(5, 6)) else .y # 直接保留原几何 })) %>% st_set_geometry("geometry") # 确保列被识别为sf几何列
修正基础方法(处理重复ID)
如果你偶尔需要用基础R写法,只需要生成与选中行数一致的sfc元素即可:
sf2 <- sf # 对a==17的2行,生成2个相同的点组成的sfc st_geometry(sf2[sf2$a == 17,]) <- st_sfc(rep(st_point(c(12, 13)), sum(sf2$a == 17))) # 对a==16的1行,直接赋值单个点的sfc st_geometry(sf2[sf2$a == 16,]) <- st_sfc(st_point(c(5, 6)))
验证结果
运行上述代码后,你可以用st_as_text(sf2$geometry)查看更新后的几何:
st_as_text(sf2$geometry) #> [1] "POINT (0 1)" "POINT (5 6)" "POINT (12 13)" "POINT (12 13)"
完全符合你的需求!
内容的提问来源于stack exchange,提问作者waiguoren
相关产品推荐
相关产品推荐

