trabajar studio leer importar exportar desde datos con commander r csv import r-faq

studio - leer csv en r



Importación de múltiples archivos.csv en R (12)

Supongamos que tenemos una carpeta que contiene múltiples archivos data.csv, cada uno con el mismo número de variables, pero cada uno desde diferentes momentos.

¿Hay alguna manera en R de importarlos todos simultáneamente en lugar de tener que importarlos todos individualmente?

Mi problema es que tengo alrededor de 2000 archivos de datos para importar y tener que importarlos individualmente solo con el código:

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

no es muy eficiente


Además de usar lapply o alguna otra construcción de bucle en R, podría fusionar sus archivos CSV en un solo archivo.

En Unix, si los archivos no tienen encabezados, entonces es tan fácil como:

cat *.csv > all.csv

o si hay encabezados, y puede encontrar una cadena que coincida con los encabezados y solo los encabezados (es decir, supongamos que todas las líneas del encabezado comienzan con "Edad"), usted haría:

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

Creo que en Windows podrías hacer esto con COPY y SEARCH (o FIND algo) en el cuadro de comandos de DOS, pero ¿por qué no instalar cygwin y obtener el poder del shell de comandos de Unix?


Algo como lo siguiente debería funcionar:

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

Esto supone que tiene esos CSV en un solo directorio, su directorio de trabajo actual, y que todos ellos tienen la extensión en minúscula .csv .

Actualizar

Solución rápida y sucia para obtener data.frames separados ("sucios" porque no me he molestado en limpiar la extensión .csv , pero eso es bastante fácil de hacer con algunos regex ):

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

O bien, sin assign , y para demostrar (1) cómo se puede limpiar el nombre del archivo y (2) mostrar cómo usar list2env , puede intentar lo siguiente:

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


Aquí hay otras opciones para convertir los archivos .csv en un data.frame. Usando las funciones de base R Este es un orden de magnitud más lento que las opciones a continuación.

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

Editar: - Unas pocas opciones más usando data.table y readr

Una versión de fread() , que es una función del paquete data.table . Esta debería ser la opción más rápida.

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

Usando readr , que es un nuevo paquete hadley para leer archivos csv. Un poco más lento que fread pero con diferentes funcionalidades.

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


Basándose en los comentarios de dnlbrk, asignar puede ser considerablemente más rápido que list2env para archivos grandes.

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)

Al establecer el argumento full.names en verdadero, obtendrá la ruta completa a cada archivo como una cadena de caracteres separada en su lista de archivos, por ejemplo, List_of_file_paths [1] será algo así como "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) }

Puede usar el archivo fread o base R del archivo data.table en lugar de read_csv. El paso file_name le permite ordenar el nombre para que cada cuadro de datos no permanezca con la ruta completa al archivo como su nombre. Puede ampliar su ciclo para hacer otras cosas en la tabla de datos antes de transferirlo al entorno global, por ejemplo:

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


En mi opinión, la mayoría de las otras respuestas están obsoletas por rio::import_list , que es un sucinto rio::import_list :

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

Cualquier argumento adicional se pasa a rio::import . rio puede tratar casi cualquier formato de archivo que R pueda leer, y usa el data.table de fread siempre que sea posible, por lo que también debe ser rápido.


Este es el código que desarrollé para leer todos los archivos csv en R. Creará un dataframe para cada archivo csv individualmente y titulará ese dataframe con el nombre original del archivo (eliminando espacios y el .csv) ¡Espero que lo encuentres útil!

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=""))) }


Esto es parte de mi script

#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) }


Lo uso con éxito:

xlist<-list.files(pattern = "*.csv") for(i in xlist) { x <- read.csv((i)) assign(i, x) }


Puede usar el excelente paquete sparklyr para esto:

# 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()


Una solución tidyverse rápida y sucinta: (más del doble de rápido que read.csv la Base R )

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

El fread() puede incluso reducir esos tiempos de carga a la mitad.

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

El argumento stringsAsFactors = FALSE mantiene el factor de marco de datos libre.

Si el encasillado de tipo está siendo descarado, puede forzar todas las columnas a ser como caracteres con el argumento col_types .

tbl <- list.files(pattern = "*.csv") %>% map_df(~read_csv(., col_types = cols(.default = "c")))

Si desea sumergirse en subdirectorios para construir su lista de archivos para eventualmente enlazar, asegúrese de incluir el nombre de ruta, así como registrar los archivos con sus nombres completos en su lista. Esto permitirá que el trabajo de enlace continúe fuera del directorio actual. (Pensando en los nombres completos de las rutas como operando como pasaportes para permitir el movimiento de vuelta a través de las ''fronteras'' del directorio).

tbl <- list.files(path = "./subdirectory/", pattern = "*.csv", full.names = T) %>% map_df(~read_csv(., col_types = cols(.default = "c")))

Como Hadley describe here (aproximadamente a mitad de camino):

map_df(x, f) es efectivamente lo mismo que do.call("rbind", lapply(x, f)) ....

Característica de bonificación : agregar nombres de archivo a los registros por solicitud de función Niks en los comentarios a continuación:
* Agregue el filename del filename original a cada registro.

Código explicado: realice una función para agregar el nombre del archivo a cada registro durante la lectura inicial de las tablas. Luego use esa función en lugar de la función simple read_csv() .

read_plus <- function(flnm) { read_csv(flnm) %>% mutate(filename = flnm) } tbl_with_sources <- list.files(pattern = "*.csv", full.names = T) %>% map_df(~read_plus(.))

(Los métodos de manejo de la conversión y del subdirectorio también se pueden manejar dentro de la función read_plus() de la misma manera que se ilustra en la segunda y tercera variantes sugeridas anteriormente).

### Benchmark Code & Results library(tidyverse) library(data.table) library(microbenchmark) ### Base R Approaches #### Instead of a dataframe, this approach creates a list of lists #### removed from analysis as this alone doubled analysis time reqd # lapply_read.delim <- function(path, pattern = "*.csv") { # temp = list.files(path, pattern, full.names = TRUE) # myfiles = lapply(temp, read.delim) # } #### `read.csv()` do.call_rbind_read.csv <- function(path, pattern = "*.csv") { files = list.files(path, pattern, full.names = TRUE) do.call(rbind, lapply(files, function(x) read.csv(x, stringsAsFactors = FALSE))) } map_df_read.csv <- function(path, pattern = "*.csv") { list.files(path, pattern, full.names = TRUE) %>% map_df(~read.csv(., stringsAsFactors = FALSE)) } ### *dplyr()* #### `read_csv()` lapply_read_csv_bind_rows <- function(path, pattern = "*.csv") { files = list.files(path, pattern, full.names = TRUE) lapply(files, read_csv) %>% bind_rows() } map_df_read_csv <- function(path, pattern = "*.csv") { list.files(path, pattern, full.names = TRUE) %>% map_df(~read_csv(., col_types = cols(.default = "c"))) } ### *data.table* / *purrr* hybrid map_df_fread <- function(path, pattern = "*.csv") { list.files(path, pattern, full.names = TRUE) %>% map_df(~fread(., stringsAsFactors = FALSE)) } ### *data.table* rbindlist_fread <- function(path, pattern = "*.csv") { files = list.files(path, pattern, full.names = TRUE) rbindlist(lapply(files, function(x) fread(x, stringsAsFactors = FALSE))) } do.call_rbind_fread <- function(path, pattern = "*.csv") { files = list.files(path, pattern, full.names = TRUE) do.call(rbind, lapply(files, function(x) fread(x, stringsAsFactors = FALSE))) } read_results <- function(dir_size){ microbenchmark( # lapply_read.delim = lapply_read.delim(dir_size), # too slow to include in benchmarks do.call_rbind_read.csv = do.call_rbind_read.csv(dir_size), map_df_read.csv = map_df_read.csv(dir_size), lapply_read_csv_bind_rows = lapply_read_csv_bind_rows(dir_size), map_df_read_csv = map_df_read_csv(dir_size), rbindlist_fread = rbindlist_fread(dir_size), do.call_rbind_fread = do.call_rbind_fread(dir_size), map_df_fread = map_df_fread(dir_size), times = 10L) } read_results_lrg_mid_mid <- read_results(''./testFolder/500MB_12.5MB_40files'') print(read_results_lrg_mid_mid, digits = 3) read_results_sml_mic_mny <- read_results(''./testFolder/5MB_5KB_1000files/'') read_results_sml_tny_mod <- read_results(''./testFolder/5MB_50KB_100files/'') read_results_sml_sml_few <- read_results(''./testFolder/5MB_500KB_10files/'') read_results_med_sml_mny <- read_results(''./testFolder/50MB_5OKB_1000files'') read_results_med_sml_mod <- read_results(''./testFolder/50MB_5OOKB_100files'') read_results_med_med_few <- read_results(''./testFolder/50MB_5MB_10files'') read_results_lrg_sml_mny <- read_results(''./testFolder/500MB_500KB_1000files'') read_results_lrg_med_mod <- read_results(''./testFolder/500MB_5MB_100files'') read_results_lrg_lrg_few <- read_results(''./testFolder/500MB_50MB_10files'') read_results_xlg_lrg_mod <- read_results(''./testFolder/5000MB_50MB_100files'') print(read_results_sml_mic_mny, digits = 3) print(read_results_sml_tny_mod, digits = 3) print(read_results_sml_sml_few, digits = 3) print(read_results_med_sml_mny, digits = 3) print(read_results_med_sml_mod, digits = 3) print(read_results_med_med_few, digits = 3) print(read_results_lrg_sml_mny, digits = 3) print(read_results_lrg_med_mod, digits = 3) print(read_results_lrg_lrg_few, digits = 3) print(read_results_xlg_lrg_mod, digits = 3) # display boxplot of my typical use case results & basic machine max load par(oma = c(0,0,0,0)) # remove overall margins if present par(mfcol = c(1,1)) # remove grid if present par(mar = c(12,5,1,1) + 0.1) # to display just a single boxplot with its complete labels boxplot(read_results_lrg_mid_mid, las = 2, xlab = "", ylab = "Duration (seconds)", main = "40 files @ 12.5MB (500MB)") boxplot(read_results_xlg_lrg_mod, las = 2, xlab = "", ylab = "Duration (seconds)", main = "100 files @ 50MB (5GB)") # generate 3x3 grid boxplots par(oma = c(12,1,1,1)) # margins for the whole 3 x 3 grid plot par(mfcol = c(3,3)) # create grid (filling down each column) par(mar = c(1,4,2,1)) # margins for the individual plots in 3 x 3 grid boxplot(read_results_sml_mic_mny, las = 2, xlab = "", ylab = "Duration (seconds)", main = "1000 files @ 5KB (5MB)", xaxt = ''n'') boxplot(read_results_sml_tny_mod, las = 2, xlab = "", ylab = "Duration (milliseconds)", main = "100 files @ 50KB (5MB)", xaxt = ''n'') boxplot(read_results_sml_sml_few, las = 2, xlab = "", ylab = "Duration (milliseconds)", main = "10 files @ 500KB (5MB)",) boxplot(read_results_med_sml_mny, las = 2, xlab = "", ylab = "Duration (microseconds) ", main = "1000 files @ 50KB (50MB)", xaxt = ''n'') boxplot(read_results_med_sml_mod, las = 2, xlab = "", ylab = "Duration (microseconds)", main = "100 files @ 500KB (50MB)", xaxt = ''n'') boxplot(read_results_med_med_few, las = 2, xlab = "", ylab = "Duration (seconds)", main = "10 files @ 5MB (50MB)") boxplot(read_results_lrg_sml_mny, las = 2, xlab = "", ylab = "Duration (seconds)", main = "1000 files @ 500KB (500MB)", xaxt = ''n'') boxplot(read_results_lrg_med_mod, las = 2, xlab = "", ylab = "Duration (seconds)", main = "100 files @ 5MB (500MB)", xaxt = ''n'') boxplot(read_results_lrg_lrg_few, las = 2, xlab = "", ylab = "Duration (seconds)", main = "10 files @ 50MB (500MB)")

Caso de uso de Middling

Caso de uso más grande

Variedad de casos de uso

Filas: conteos de archivos (1000, 100, 10)
Columnas: tamaño del marco de datos final (5MB, 50MB, 500MB)
(haga clic en la imagen para ver el tamaño original)

Los resultados de la base R son mejores para los casos de uso más pequeños donde la carga de llevar las bibliotecas C de purrr y dplyr a superar las ganancias de rendimiento que se observan cuando se realizan tareas de procesamiento a mayor escala.

si desea ejecutar sus propias pruebas, puede encontrar útil este script bash.

for ((i=1; i<=$2; i++)); do cp "$1" "${1:0:8}_${i}.csv"; done

bash what_you_name_this_script.sh "fileName_you_want_copied" 100 creará 100 copias de su archivo numeradas secuencialmente (después de los 8 caracteres iniciales del nombre de archivo y un guión bajo).

Atribuciones y apreciaciones

Con un agradecimiento especial a:

  • Tyler Rinker y por demostrar microbenchmark.
  • Jake Kaupp por presentarme map_df() aquí .
  • David McLaughlin para comentarios útiles sobre la mejora de las visualizaciones y discutir / confirmar las inversiones de rendimiento observadas en el archivo pequeño, resultados de análisis de pequeños cuadros de datos.

Usando plyr::ldply hay aproximadamente un aumento del 50% de velocidad al habilitar la opción .parallel mientras lee archivos de 400 csv de aproximadamente 30-40 MB cada uno. El ejemplo incluye una barra de progreso de texto.

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)


si desea recopilar diferentes archivos csv en un data.frame, puede usar lo siguiente. tenga en cuenta que el "x" data.frame debe crearse de antemano.

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