Что не так с моей функцией загрузки нескольких файлов .csv в один кадр данных в 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

В чем моя ошибка? Кто-нибудь может объяснить?


person Sivanantham C    schedule 21.04.2014    source источник
comment
если Coursera действительно привела вас сюда, прочтите отличное практическое задание, которое они предоставили в первую очередь. (На сегодняшний день ссылка: github.com/rdpeng/practice_assignment/blob /мастер/)   -  person pugmarx    schedule 22.07.2015


Ответы (6)


В вашей функции много ненужного кода. Вы можете упростить его до:

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 + rbind относительно медленный. Вы можете обнаружить, что dplyr::bind_rows или data.table::rbindlist значительно быстрее.

person hadley    schedule 21.04.2014
comment
Или теперь dplyr::bind_rows вместо dplyr::rbind_list, который устарел. - person Sam Firke; 17.04.2015
comment
кроме того, использование readr::read_csv намного быстрее, чем read.csv. - person amc; 29.10.2016

Чтобы обновить ответ профессора Уикхема выше кодом из более новой 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() здесь.

person leerssej    schedule 14.02.2017
comment
Это лучший ответ, учитывая текущее состояние Tidyverse. - person HAVB; 28.06.2017

Это можно сделать очень лаконично с помощью dplyr и purrr из tidyverse. Где x — это список имен ваших CSV-файлов, которые вы можете просто использовать:

bind_rows(map(x, read.csv))

Сопоставление read.csv с x дает список dfs, который bind_rows затем аккуратно объединяет!

person CClarke    schedule 31.05.2018
comment
Очень элегантный. Спасибо! - person Megatron; 13.01.2020

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

readFilesInDirectory <- function(directory, pattern){
  files <- list.files(path = directory,pattern = pattern)
  for (f in files){
    file <- paste(directory,files, sep ="")
    temp <- lapply(file, fread, sep=",")
    data <- rbindlist( temp )
  }
  return(data)
}
person LBes    schedule 13.03.2019

В вашей текущей функции 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 в глобальной среде.

person CHP    schedule 21.04.2014

person    schedule
comment
Код работает - изменен из кода Даниэля Марселино. Спасибо, что нашли время, чтобы прокомментировать. - person Dave Headrick; 17.10.2016