读取 shapefile 列表并在 R 中行绑定它们(最好使用整洁的语法和 sf)

Read in a list of shapefiles and row bind them in R (preferably using tidy syntax and sf)

我有一个目录,其中包含 50 个城市的一堆 shapefile(并且会积累更多)。它们分为三组:城市的政治边界(CityA_CD.shp、CityB_CD.shp 等)、社区(CityA_Neighborhoods.shp、CityB_Neighborhoods.shp 等)和人口普查区( CityA_blocks.shp、CityB_blocks.shp 等)。它们使用通用的文件命名语法,具有相同的属性变量集,并且都在同一个 CRS 中。 (我使用 QGIS 将它们全部转换为这样。)我需要编写每组文件(政治边界、社区、块)的列表以读取为 sf 对象,然后绑定行以为每个组创建一个大的 sf 对象.但是,我 运行 在 R 中开发此工作流时遇到了一致的问题。

library(tidyverse)
library(sf)
library(mapedit)

# This first line succeeds in creating a character string of the files that match the regex pattern.
filenames <- list.files("Directory", pattern=".*_CDs.*shp", full.names=TRUE)

# This second line creates a list object from the files.
shapefile_list <- lapply(filenames, st_read)

# This third line (adopted from https://github.com/r-spatial/sf/issues/798) fails as follows.
districts <- mapedit:::combine_list_of_sf(shapefile_list)
Error: Column `District_I` cant be converted from character to numeric

# This fourth line fails in an apparently different way (also adopted from https://github.com/r-spatial/sf/issues/798).
districts <- do.call(what = sf:::rbind.sf, args = shapefile_list)
Error in CPL_get_z_range(obj, 2) : z error - expecting three columns;

第一个错误似乎表明我的一个 shapefile 对于公共变量 District_I 有一个不正确的变量 class 但 R 没有提供任何信息来提示我哪个文件导致了错误.

第二个错误似乎是在寻找 z 坐标,但只在几何属性中找到 x 和 y。

关于这方面我有四个问题:

  1. 我如何让 R 识别它正在尝试读取和绑定的列表项导致导致进程停止的错误?
  2. 如何强制 R 忽略不兼容问题并将变量 class 强制转换为字符,以便我可以处理 R 中的变量不一致(如果是这样的话)?
  3. 我怎样才能完全从导致错误的读取 sf 对象中删除一个变量(即忽略进程中所有 read_sf 调用的 District_I)?
  4. 更一般地说,这是怎么回事,我该如何解决第二个错误?

感谢大家一如既往的帮助。

P.S.: 我知道这个 post 不是 "reproducible" 所需的方式,但我不知道如何做到这一点,所以除了复制所有的内容我的形状文件。如果我在这一点上有误,我很乐意接受这方面的任何智慧。

更新: 我已经 运行

filenames <- list.files("Directory", pattern=".*_CDs.*shp", full.names=TRUE)
shapefile_list <- lapply(filenames, st_read)
districts <- mapedit:::combine_list_of_sf(shapefile_list)

成功处理了三个 shapefile 的子集。因此,我已经确认在 运行 对整批代码进行 运行 处理时,其中一个文件中的列 District_I 之间存在一些 class 冲突,从而导致延迟。但同样,我需要错误来识别导致问题的文件名,以便我可以在文件中修复它,或者需要代码强制 District_I 为所有文件中的字符(这是我想要的 class那个变量无论如何都在)。

注意事项,特别是关于 Pablo 的建议:

districts <- do.call(what = dplyr::rbind_all, shapefile_list)

导致错误 Error in (function (x, id = NULL) : unused argument

后跟一长串数字和坐标。所以,

mapedit:::combine_list_of_sf(shapefile_list)

绝对是从列表中读取并合并文件的机制,但我仍然需要一种方法来诊断跨 shapefile 的列不兼容错误的来源。

因此,在 Pablo(以及他的 link 到 https://community.rstudio.com/t/simplest-way-to-modify-the-same-column-in-multiple-dataframes-in-a-list/13076)的多次烦恼和一些很好的指导之后,以下作品:

library(tidyverse)
library(sf)

# Reads in all shapefiles from Directory that include the string "_CDs".
filenames <- list.files("Directory", pattern=".*_CDs.*shp", full.names=TRUE)

# Applies the function st_read from the sf package to each file saved as a character string to transform the file list to a list object.
shapefile_list <- lapply(filenames, st_read)

# Creates a function that transforms a problem variable to class character for all shapefile reads.
my_func <- function(data, my_col){
  my_col <- enexpr(my_col)

  output <- data %>% 
    mutate(!!my_col := as.character(!!my_col))
}

# Applies the new function to our list of shapefiles and specifies "District_I" as our problem variable.
districts <- map_dfr(shapefile_list, ~my_func(.x, District_I))