运行GitHub来源R代码时dplyr::mutate()触发s2几何报错如何解决
报错原因
这个错误是sf 1.0版本后默认启用S2球面几何引擎导致的:你调用的rnaturalearth中分辨率世界国界数据存在自相交的拓扑错误(报错提示的Loop 120边交叉就是典型的无效几何特征),S2引擎对几何合法性校验远严格于旧版平面几何引擎,因此mark_land()做陆海点匹配时直接抛出错误,和你前面的配置、数据加载逻辑无关。
解决方案
按优先级从高到低选择:
方案1:修复矢量几何(推荐,不损失计算精度)
加载世界sf对象后立刻做几何修复,从根源解决无效要素问题,在你原有加载world的代码后追加一行即可:world <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf") # 修复所有无效几何 world <- sf::st_make_valid(world)如果修复后仍报错,说明裁剪到研究区后生成的新几何存在拓扑问题,可以先按你的经纬度范围裁剪陆面矢量,再做二次修复,减少不必要的全球要素干扰:
# 生成研究区范围框 study_box <- sf::st_bbox( c(xmin = lonrange[1], xmax = lonrange[2], ymin = latrange[1], ymax = latrange[2]), crs = 4326 ) %>% sf::st_as_sfc() # 裁剪+修复陆面数据 world_crop <- sf::st_intersection(world, study_box) %>% sf::st_make_valid()之后修改
01-helpers.R中mark_land()函数内部调用的陆面矢量对象为修复后的world_crop即可。方案2:临时关闭S2引擎(快速跑通流程用)
如果不想修改helper文件的内部逻辑,可以在运行数据处理代码前全局关闭S2引擎,回退到旧版平面几何计算模式,低分辨率区域分析的结果偏差基本可忽略:# 放在alldat_list处理步骤之前运行 sf::sf_use_s2(FALSE)*注意:该方法属于绕过校验的临时方案,跨180度经线、高纬度区域的空间计算可能出现明显偏差,正式出结果前建议换回方案1。
额外排查项
如果上述方案都不生效,检查两个细节:- 打开
01-helpers.R看mark_land()的内部实现,确认函数内没有单独加载其他未做几何修复的sf矢量对象 - 临时把
mark_land()里的buffer_in_km = 250参数调小,过大的缓冲区在S2引擎下也可能生成自相交的无效几何 - 可以把
ne_countries()的scale参数从"medium"换成"small",低分辨率国界数据的拓扑错误更少。
- 打开
内容的提问来源于stack exchange,提问作者oliver
相关产品推荐
相关产品推荐

