Прочтите список шейп-файлов и привяжите их в R (желательно с использованием аккуратного синтаксиса и sf)

У меня есть каталог с кучей шейп-файлов для 50 городов (и их накопится еще). Они делятся на три группы: политические границы городов (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;

Первая ошибка, похоже, указывает на то, что в одном из моих шейп-файлов указан неправильный класс переменной для общей переменной. District_I но R не предоставляет информации, чтобы понять, какой файл вызывает ошибку.

Вторая ошибка, похоже, ищет координату z, но находит только x и y в атрибуте геометрии.

У меня четыре вопроса по этому поводу:

  1. Как я могу заставить R определить, какой элемент списка он пытается прочитать, а привязка вызывает ошибку, останавливающую процесс?
  2. Как я могу заставить R игнорировать проблему несовместимости и принуждать класс переменных к символу, чтобы я мог справиться с несогласованностью переменных (если это так) в R?
  3. Как я могу полностью удалить переменную из прочитанных объектов sf, вызывающих ошибку (т.е. опустить District_I для всех read_sf звонки в процессе)?
  4. В общем, что происходит и как я могу решить вторую ошибку?

Всем как всегда спасибо за помощь.

PS: Я знаю, что этот пост нельзя "воспроизвести" желаемым образом, но я не уверен, как это сделать, кроме копирования содержимого всех моих шейп-файлов. Если я ошибаюсь в этом вопросе, я с радостью приму любую мудрость на этот счет.

ОБНОВЛЕНИЕ: я бегал

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

успешно на подмножестве из трех шейп-файлов. Итак, я подтвердил, что существует некоторый конфликт классов между столбцомDistrict_Iв одном из файлов, вызывающих задержку при запуске кода в полном пакете. Но опять же, мне нужна ошибка, чтобы идентифицировать имя файла, вызывающее проблему, чтобы я мог исправить ее в файле ИЛИ нужен код для принужденияDistrict_I для символа во всех файлах (это класс, в котором я все равно хочу, чтобы эта переменная была).

Примечание, особенно в отношении рекомендации Пабло:

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

приводит к ошибкеError in (function (x, id = NULL) : unused argument

за которой следует длинная строка цифр и координат. Так,

mapedit:::combine_list_of_sf(shapefile_list)

определенно является механизмом для чтения из списка и объединения файлов, но мне все еще нужен способ диагностировать источник ошибки несовместимости столбцов в шейп-файлах.

1 ответ

Итак, после долгих переживаний и отличных указаний Пабло (и его ссылки на 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))
Другие вопросы по тегам