读取 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。
关于这方面我有四个问题:
- 我如何让 R 识别它正在尝试读取和绑定的列表项导致导致进程停止的错误?
- 如何强制 R 忽略不兼容问题并将变量 class 强制转换为字符,以便我可以处理 R 中的变量不一致(如果是这样的话)?
- 我怎样才能完全从导致错误的读取 sf 对象中删除一个变量(即忽略进程中所有
read_sf
调用的 District_I
)?
- 更一般地说,这是怎么回事,我该如何解决第二个错误?
感谢大家一如既往的帮助。
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))
我有一个目录,其中包含 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。
关于这方面我有四个问题:
- 我如何让 R 识别它正在尝试读取和绑定的列表项导致导致进程停止的错误?
- 如何强制 R 忽略不兼容问题并将变量 class 强制转换为字符,以便我可以处理 R 中的变量不一致(如果是这样的话)?
- 我怎样才能完全从导致错误的读取 sf 对象中删除一个变量(即忽略进程中所有
read_sf
调用的District_I
)? - 更一般地说,这是怎么回事,我该如何解决第二个错误?
感谢大家一如既往的帮助。
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))