Импорт нескольких.csv файлы в R

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

моя проблема в том, что у меня есть около 2000 файлов данных для импорта и их нужно импортировать по отдельности, просто используя код:

read.delim(file="filename", header=TRUE, sep="t")

не очень эффективно.

13 ответов


что-то вроде следующего должно привести к тому, что каждый фрейм данных будет отдельным элементом в одном списке:

temp = list.files(pattern="*.csv")
myfiles = lapply(temp, read.delim)

это предполагает, что у вас есть эти CSV в одном каталоге-ваш текущий рабочий каталог-и что все они имеют расширение нижнего регистра .csv.

если вы хотите объединить эти фреймы данных в один фрейм данных, см. решения в других ответах, используя такие вещи, как do.call(rbind,...), dplyr::bind_rows() или data.table::rbindlist().

если вы действительно, каждый фрейм данных в отдельном объекте, хотя это часто нецелесообразно, вы можете сделать следующее с помощью assign:

temp = list.files(pattern="*.csv")
for (i in 1:length(temp)) assign(temp[i], read.csv(temp[i]))

или assign, и продемонстрировать, (1) как имя файла может быть очищено и (2) показывают, как использовать list2env, вы можете попробовать следующее:

temp = list.files(pattern="*.csv")
list2env(
  lapply(setNames(temp, make.names(gsub("*.csv$", "", temp))), 
         read.csv), envir = .GlobalEnv)

но опять же, это часто лучше оставить их в одном списке.


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

# Get the files names
files = list.files(pattern="*.csv")
# First apply read.csv, then rbind
myfiles = do.call(rbind, lapply(files, function(x) read.csv(x, stringsAsFactors = FALSE)))

Edit: - еще несколько дополнительных вариантов, с помощью data.table и readr

A fread() версия, которая является функцией . Это должен быть самый быстрый вариант.

library(data.table)
DT = do.call(rbind, lapply(files, fread)
# the same using `rbindlist()`
DT = rbindlist(lapply(files, fread))

используя readr, который является новым пакетом hadley для чтения csv-файлов. Немного медленнее, чем fread, но с различными функциональными возможностями.

library(readr)
library(dplyr)
tbl = lapply(files, read_csv) %>% bind_rows()

быстрый и лаконичный tidyverse решение: (более чем в два раза быстрее база R read.csv)

tbl <-
    list.files(pattern = "*.csv") %>% 
    map_df(~read_csv(.))

данные.таблица ' s fread() смогите даже отрезать те времена нагрузки в половине.

library(data.table)

tbl_fread <- 
    list.files(pattern = "*.csv") %>% 
    map_df(~fread(., stringsAsFactors = FALSE))

на stringsAsFactors = FALSE аргумент сохраняет фактор фрейма данных свободным.

если типизация является нахальной, вы можете заставить все столбцы быть символами с col_types аргумент.

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))....

Бонус - добавление имен файлов в записи на запрос функции Niks в комментариях ниже:
* Добавить оригинал filename для каждой записи.

код объяснен: сделайте функцию для добавления имени файла к каждой записи во время начального чтения таблиц. Затем используйте эту функцию вместо простого


а также с помощью lapply или какая-либо другая конструкция цикла в R вы можете объединить свои CSV-файлы в один файл.

в Unix, если файлы не имели заголовков, то его так просто, как:

cat *.csv > all.csv

или если есть заголовки, и вы можете найти строку, которая соответствует заголовкам и только заголовкам (т. е. предположим, что строки заголовков начинаются с "возраста"), вы бы сделали:

cat *.csv | grep -v ^Age > all.csv

Я думаю, что в Windows вы могли бы сделать это с COPY и SEARCH (или FIND или что-то) от Командное поле DOS, но почему бы не установить cygwin и получить власть командной оболочки Unix?


это код, который я разработал для чтения всех csv-файлов в R. он создаст фрейм данных для каждого csv-файла отдельно и заголовок, который dataframe оригинальное имя файла (удаление пробелов и .csv) надеюсь, вы найдете это полезным!

path <- "C:/Users/cfees/My Box Files/Fitness/"
files <- list.files(path=path, pattern="*.csv")
for(file in files)
{
perpos <- which(strsplit(file, "")[[1]]==".")
assign(
gsub(" ","",substr(file, 1, perpos-1)), 
read.csv(paste(path,file,sep="")))
}

используя plyr::ldply существует примерно 50% увеличение скорости, включив .parallel опция при чтении 400 csv файлов примерно 30-40 МБ каждый. Пример включает индикатор выполнения текста.

library(plyr)
library(data.table)
library(doSNOW)

csv.list <- list.files(path="t:/data", pattern=".csv$", full.names=TRUE)

cl <- makeCluster(4)
registerDoSNOW(cl)

pb <- txtProgressBar(max=length(csv.list), style=3)
pbu <- function(i) setTxtProgressBar(pb, i)
dt <- setDT(ldply(csv.list, fread, .parallel=TRUE, .paropts=list(.options.snow=list(progress=pbu))))

stopCluster(cl)

на мой взгляд, большинство других ответов заменен на rio::import_list, который является кратким однострочным:

library(rio)
my_data <- import_list(dir("path_to_directory", pattern = ".csv", rbind = TRUE))

любые дополнительные аргументы передаются rio::import. rio может иметь дело практически с любым форматом файла R может читать, и он использует data.table ' s fread где это возможно, поэтому он должен быть быстрым.


основываясь на комментарии dnlbrk, assign может быть значительно быстрее, чем list2env для больших файлов.

library(readr)
library(stringr)

List_of_file_paths <- list.files(path ="C:/Users/Anon/Documents/Folder_with_csv_files/", pattern = ".csv", all.files = TRUE, full.names = TRUE)

установив полный.names аргумент true, вы получите полный путь к каждому файлу в виде отдельной символьной строки в вашем списке файлов, например, List_of_file_paths[1] будет что-то вроде "C:/Users/Anon/Documents/Folder_with_csv_files/file1 - ... csv"

for(f in 1:length(List_of_filepaths)) {
  file_name <- str_sub(string = List_of_filepaths[f], start = 46, end = -5)
  file_df <- read_csv(List_of_filepaths[f])  
  assign( x = file_name, value = file_df, envir = .GlobalEnv)
}

вы можете использовать данные.чтение fread или base R пакета таблицы.csv вместо read_csv. Этот file_name шаг позволяет упорядочить имя, так что каждый фрейм данных не остается с полным путем к файлу, как это имя. Вы можете расширить свой цикл, чтобы сделать что-то еще в таблице данных перед передачей ее в глобальную среду, например:

for(f in 1:length(List_of_filepaths)) {
  file_name <- str_sub(string = List_of_filepaths[f], start = 46, end = -5)
  file_df <- read_csv(List_of_filepaths[f])  
  file_df <- file_df[,1:3] #if you only need the first three columns
  assign( x = file_name, value = file_df, envir = .GlobalEnv)
}

моя вилка принятого ответа немного быстрее и удаляет .csv от имени объекта в р.

temp = list.files(pattern="*.csv")
for (i in 1:length(temp)) assign(gsub(".csv", "", temp[i]), read_csv(temp[i]))

он полагается на readr пакета (т. е. library(readr)). Вы можете сделать что-то подобное с data.table если вы хотели.


Я использую это успешно:

xlist<-list.files(pattern = "*.csv")

for(i in xlist) { 
  x <- read.csv((i))
  assign(i, x)
    }

Если вы хотите собрать разные csv-файлы в одни данные.кадр, вы можете использовать следующее. обратите внимание, что данные" x".рама должна быть создана заранее.

temp <- list.files(pattern="*.csv")
for (i in 1:length(temp)) {
    temp2 = read.csv(temp[i], header = TRUE)
    x <- rbind(x,temp2)
    }

вы можете использовать superb sparklyr пакет для этого:

# RStudio will help you get set-up with the Spark dependencies
library(sparklyr)
library(dplyr)
sc <- spark_connect(master = "local", version = "2.0.2")

df <- spark_read_csv(sc,
                     "dummy",
                     "file:////Users/bob/dev/data/results/*/*/*-metrics.csv") %>%
  collect()

Это часть моего сценария.

#This cycle read the files in a directory and assign the filenames to datasets
files <- list.files(pattern=".csv$")
for(i in files) {
    X <- read.table(i, header=TRUE)
    SN<-X$A/X$B 
    X<-cbind(X,SN)
    ds<-paste("data_",i, sep="")#this add "data_" to the name of file
    ds<-substr(ds, 1, nchar(ds)-4)#remove the last 4 char (.csv)
    assign(ds, X)
}