Что случилось с моей функцией для загрузки нескольких CSV-файлов в единый dataframe в R с помощью rbind?
Я написал следующую функцию для объединения 300 файлов .csv. Мое имя каталога – «specdata». Я выполнил следующие шаги для выполнения,
x <- function(directory) { dir <- directory data_dir <- paste(getwd(),dir,sep = "/") files <- list.files(data_dir,pattern = '\\.csv') tables <- lapply(paste(data_dir,files,sep = "/"), read.csv, header = TRUE) pollutantmean <- do.call(rbind , tables) } # Step 2: call the function x("specdata") # Step 3: inspect results head(pollutantmean) Error in head(pollutantmean) : object 'pollutantmean' not found
Какая у меня ошибка? Может кто-нибудь объяснить?
- Преобразование вложенного списка в dataframe
- Как я могу допустить, что rbind () не станет очень медленным, поскольку размер фреймворка увеличивается?
- Эффективный способ rbind data.frames с разными столбцами
В вашей функции много ненужного кода. Вы можете упростить его:
load_data <- function(path) { files <- dir(path, pattern = '\\.csv', full.names = TRUE) tables <- lapply(files, read.csv) do.call(rbind, tables) } pollutantmean <- load_data("specdata")
Имейте в do.call
что do.call
+ rbind
относительно медленный. Вы можете найти dplyr::bind_rows
или data.table::rbindlist
чтобы быть значительно быстрее.
Чтобы обновить ответ профессора Уикхема выше с кодом из более поздней библиотеки purrr
которую он соавтор с Лионелем Генри:
Tbl <- list.files(pattern="*.csv") %>% map_df(~read_csv(.))
Если приведение типов навязчиво, вы можете заставить все столбцы быть такими же символами.
Tbl <- list.files(pattern="*.csv") %>% map_df(~read_csv(., col_types = cols(.default = "c")))
Если вы хотите окунуться в подкаталоги, чтобы создать список файлов для окончательного связывания, тогда обязательно укажите имя пути, а также зарегистрируйте файлы с их полными именами в своем списке. Это позволит работать с привязкой за пределами текущего каталога. (Думая о полных дорожных именах как работающих как паспорта, чтобы позволить перемещаться по границам «границ» каталога.)
Tbl <- list.files(path = "./subdirectory/", pattern="*.csv", full.names = T) %>% map_df(~read_csv(., col_types = cols(.default = "c")))
Как описывает здесь профессор Уикхем (примерно на полпути):
map_df(x, f)
фактически совпадает сdo.call("rbind", lapply(x, f))
но под капотом намного эффективнее.
и спасибо Джейку Кауппу за то, что вы представили мне map_df () здесь .
```{r echo = FALSE, warning = FALSE, message = FALSE} setwd("~/Data/R/BacklogReporting/data/PastDue/global/") ## where file are located path = "~/Data/R/BacklogReporting/data/PastDue/global/" out.file <- "" file.names <- dir(path, pattern = ".csv") for(i in 1:length(file.names)){ file <- read.csv(file.names[i], header = TRUE, stringsAsFactors = FALSE) out.file <- rbind(out.file, file) } write.csv(out.file, file = "~/Data/R/BacklogReporting/data/PastDue/global/global_stacked/past_due_global_stacked.csv", row.names = FALSE) ## directory to write stacked file to past_due_global_stacked <- read.csv("C:/Users/E550143/Documents/Data/R/BacklogReporting/data/PastDue/global/global_stacked/past_due_global_stacked.csv", stringsAsFactors = FALSE) files <- list.files(pattern = "\\.csv$") %>% t() %>% paste(collapse = ", ") ```
Это можно сделать очень кратко с dplyr и purrr с tidyverse. Где x – список имен ваших файлов csv, вы можете просто использовать:
bind_rows(map(x, read.csv))
Отображение read.csv в x создает список dfs, который bind_rows затем аккуратно объединяет!
В вашей текущей функции pollutantmean
доступен только в рамках функции x
. Измените свою функцию на эту
x <- function(directory) { dir <- directory data_dir <- paste(getwd(),dir,sep = "/") files <- list.files(data_dir,pattern = '\\.csv') tables <- lapply(paste(data_dir,files,sep = "/"), read.csv, header = TRUE) assign('pollutantmean',do.call(rbind , tables)) }
assign
должен поместить результат do.call(rbind, tables)
в переменную, называемую pollutantmean
в глобальной среде.