2012-07-11 25 views
112

Supongamos que tenemos una carpeta que contiene varios archivos data.csv, cada uno con el mismo número de variables pero cada uno desde diferentes momentos.Importación de varios archivos .csv en R

¿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 de forma individual sólo mediante el uso del código:

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

no es muy eficiente.

Respuesta

155

algo como lo siguiente debería funcionar:

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

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

actualización

solución rápida y sucia para obtener data.frames separados ("sucia" porque no he tomado la molestia de limpiar la extensión .csv, pero eso es bastante fácil de hacer con un poco de regex):

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

O, sin assign, y para demostrar (1) cómo el nombre de archivo puede ser limpiado y (2) muestran cómo utilizar list2env, puede intentar lo siguiente:

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

Gracias! esto funciona muy bien ... ¿cómo voy a nombrar cada archivo que acabo de importar para que pueda llamarlos fácilmente? –

+0

si puede mostrarnos las primeras líneas de algunos de sus archivos, es posible que tengamos algunas sugerencias: edite su pregunta para eso. – Spacedman

+1

El código anterior funciona perfectamente para importarlos como objetos únicos, pero cuando intento recuperar una columna del conjunto de datos, no la reconoce, ya que es solo un objeto, no un marco de datos , es decir, mi versión del código anterior es: setwd ('C:/Users/nueva/escritorio/inmersiones/0904_003') temp <-list.files (patrón = "* csv") ddives <- lapply (temperatura, read.csv) Así que ahora cada archivo se llama ddives [n], pero ¿cómo voy a escribir un bucle para convertirlos en todos los marcos de datos en lugar de objetos únicos? Puedo lograr esto de forma individual utilizando el operador data.frame, pero no estoy seguro de cómo hacerlo. @mrdwab –

22

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 tenían cabeceras, entonces su tan fácil como:

cat *.csv > all.csv 

o si hay cabeceras, y se puede encontrar una cadena que coincide con los encabezados y sólo los encabezados (por ejemplo, líneas de cabecera supongamos todos comienzan con "Edad"), que haría:

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

pienso en Windows que podría hacer esto con COPY y SEARCH (o FIND o algo así) de la caja de comandos de DOS, pero ¿por qué no se instala y cygwin obtener el po wer del shell de comandos de Unix?

+0

o incluso ir con el _Git Bash_ que aparece con la instalación 'Git'? –

-3

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

Este es el código que he desarrollado para leer todos los archivos CSV en R. Se va a crear una trama de datos para cada archivo CSV de forma individual y el título que trama de datos el nombre original del archivo (espacios y eliminando la csv) Te espero ¡encuentra ú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=""))) 
} 
59

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: - A pocas opciones más adicionales utilizando data.table y readr

Una versión 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 de Hadley para la lectura de archivos CSV. Un poco más lento que fread pero con diferentes funcionalidades.

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

¿Cómo funciona esto frente a Reduce (rbind, lapply (...))? Solo estoy aprendiendo R pero mi conjetura es menos efectiva – aaron

+4

He añadido una versión 'data.table', que debería mejorar el rendimiento. – marbel

+0

¿Es posible leer solo archivos específicos? ex Archivos que contienen 'weather' en el nombre? – SoilSciGuy

-1

utilizo este éxito:

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

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

si desea recoger los diferentes archivos CSV en una hoja.de.datos, puede utilizar 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) 
    } 
2

Según el comentario 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) 

estableciendo el argumento full.names true, obtendrá la ruta completa a cada archivo como una cadena de caracteres separada en la 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) 
} 

Usted podría utilizar fread o base read.csv R del paquete 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. Se podría extender su bucle de hacer más cosas a la tabla de datos antes de transferirlos al medio ambiente 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) 
} 
26

Una rápida y más sucinta tidyverse(aka: dplyr/purrr) solución:

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

Si el encasillado es descarado, puede forzar todas las columnas para que sean como caracteres con esto.

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

Si usted está deseando que echar mano de subdirectorios para construir su lista de archivos para unirse con el tiempo, a continuación, asegúrese de incluir el nombre de la 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 las rutas completas como operando como pasaportes para permitir el movimiento de regreso a través del directorio 'fronteras'.)

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

Como Hadley describe here (a mitad de camino hacia abajo):

map_df(x, f) es efectivamente el mismo que do.call("rbind", lapply(x, f)) pero debajo del capó es mucho más eficiente.

y un agradecimiento a Jake Kaupp por presentarme a map_df()here.

función de bonificación de-añadiendo nombres de archivo a los registros por Niks función de solicitud de comentarios a continuación:
* Añadir originales filename a cada registro.

Código explicado: haga 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 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 Encasillamiento y subdirectorio enfoques de manipulación también puede ser manejado dentro de la función read_plus() de la misma manera como se ilustra en la segunda y tercera variantes sugeridas anteriormente.)

+0

tu solución funciona para mí. En esto quiero almacenar ese nombre de archivo para diferenciarlos ... ¿Es posible? – Niks

+0

@Niks - ¡Ciertamente! Simplemente escriba y cambie una pequeña función que no solo lea los archivos, sino que inmediatamente anexe un nombre de archivo para cada registro leído. Al igual que 'readAddFilename <- function (flnm) { read_csv (flnm)%>% mutate (filename = flnm) }' Luego simplemente colóquelo en el 'map_df' en lugar de la lectura simple' read_csv() ' eso está allí ahora. Puedo actualizar la entrada anterior para mostrar la función y cómo encajaría en la tubería si aún tiene preguntas o cree que serán útiles. –

3

Uso de plyr::ldply hay aproximadamente un 50% Aumente la velocidad activando 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) 
0

Puede utilizar el excelente paquete de 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() 
Cuestiones relacionadas