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

使用st_write导出sf对象时如何解决CPL_write_ogr写入错误?

解决sf对象st_write导出Shapefile的"Write error"问题

问题背景

通过tigris获取明尼苏达州乡镇层级空间数据,tidycensus获取普查区层级带人口属性的空间数据,执行st_intersection完成层级整合后,调用st_write导出Shapefile时触发以下错误:

Error in CPL_write_ogr(obj, dsn, layer, driver, as.character(dataset_options), :
Write error

用户使用的代码如下:

library(tigris)
library(sf)
library(purrr)
library(tidycensus)
library(tidyr)
library(dplyr)

##Data at township level 
#---------------------------#
MN_Township_SHP <- county_subdivisions("Minnesota", cb = TRUE)%>% st_transform(., crs=32618)
MN_Township_SHP$County <- substr(MN_Township_SHP$NAMELSADCO,1,nchar(MN_Township_SHP$NAMELSADCO)-7)
Dataset <- MN_Township_SHP

#Data at census tract level
#---------------------------#
Sys.getenv("CENSUS_API_KEY") 

my_vars <- 
  c(total_pop        = "B01003_001",
    race_denominator = "B02001_001", #Total
    white            = "B02001_002")
mn <- unique(fips_codes$state)[24]
MN_CensusTract_SHP <-map_df(mn, function(x) {
  get_acs(geography = "tract", 
          geometry = T, 
          variables = my_vars, 
          state = mn) })
MN_CensusTract_SHP <- MN_CensusTract_SHP %>% dplyr::select(-moe) 
Social_Dat <-
  MN_CensusTract_SHP %>%
  as.data.frame() %>%
  pivot_wider(names_from = variable,
              values_from = c(estimate)) %>%
  dplyr::mutate(year=2021) %>% 
  dplyr::rename_all(funs(paste0("ACS_", .))) 
Social_Dat$ACS_year <- as.double(Social_Dat$ACS_year)
Social_Dat$ACS_GEOID <- as.double(Social_Dat$ACS_GEOID)
Social_Dat <- st_as_sf(Social_Dat, sf_column_name = 'ACS_geometry')%>% st_transform(., crs=32618)

#Intersection between township and census tract levels
#---------------------------#
final_df <- st_intersection(Dataset, Social_Dat, all=TRUE)

#Export sf object as shapefile 
#---------------------------#
st_write(final_df, "Input_Intermediate/final_df.shp",  delete_layer = TRUE)

报错原因及解决方案

1. Shapefile字段名长度限制(最可能原因)

Shapefile的属性字段名最多允许10个字符,代码中通过rename_all(funs(paste0("ACS_", .)))生成的字段如ACS_race_denominator(长度18)远超限制,直接导致写入失败。

解决方法:手动重命名字段,确保长度≤10:

Social_Dat <-
  MN_CensusTract_SHP %>%
  as.data.frame() %>%
  pivot_wider(names_from = variable,
              values_from = c(estimate)) %>%
  dplyr::mutate(year=2021) %>% 
  # 自定义短字段名
  dplyr::rename(
    ACS_totpop = total_pop,
    ACS_race_den = race_denominator,
    ACS_white = white,
    ACS_year = year,
    ACS_geoid = GEOID,
    ACS_geom = geometry
  )

2. 几何类型异常或无效几何

st_intersection可能生成混合几何类型(如多边形/多多边形),或存在无效几何对象,触发OGR写入错误。

解决方法:检查并修复几何:

# 检查无效几何数量
table(st_is_valid(final_df))

# 修复无效几何
final_df <- final_df %>% st_make_valid()

# 统一转换为多多边形类型(Shapefile对混合类型支持差)
final_df <- final_df %>% st_cast("MULTIPOLYGON")

3. 数据类型不兼容

代码中将ACS_GEOID转为double类型,但GEOID是带前导零的编码(如01001020100),转为数值型会丢失前导零,且Shapefile对长数值处理容易出错。

解决方法:将GEOID保持为字符型:

# 移除原转换为double的代码,改为字符型(或直接保留原始类型)
# Social_Dat$ACS_GEOID <- as.double(Social_Dat$ACS_GEOID)
Social_Dat$ACS_geoid <- as.character(Social_Dat$ACS_geoid)

4. 输出路径问题

若Input_Intermediate文件夹不存在,或当前用户无写入权限,也会触发写入错误。

解决方法:提前创建文件夹并确认权限:

# 递归创建文件夹(若不存在)
dir.create("Input_Intermediate", recursive = TRUE, showWarnings = FALSE)

5. 换用其他格式验证数据

若以上方法无效,可先导出为GeoJSON验证数据本身是否正常(GeoJSON无Shapefile的诸多限制):

st_write(final_df, "Input_Intermediate/final_df.geojson")

若GeoJSON能正常导出,说明数据本身无问题,可尝试用ogr2ogr工具将GeoJSON转为Shapefile,或调整字段后重新导出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:05:18