2010-02-05 20 views
27

Estoy tratando de merge varios data.frames en uno data.frame. Como tengo una lista completa de archivos, intento hacerlo con una estructura de bucle.Combinar varios data.frames en un data.frame con un bucle

Hasta ahora, el enfoque de bucle funciona bien. Sin embargo, parece bastante ineficiente y me pregunto si hay un enfoque más rápido y más fácil.

Aquí está el escenario: Tengo un directorio con varios archivos .csv. Cada archivo contiene el mismo identificador que puede usarse como la variable de fusión. Como los archivos son de un tamaño bastante grande, pensé leer cada archivo uno a la vez en R en lugar de leer todos los archivos a la vez. Obtengo todos los archivos del directorio con list.files y leo los primeros dos archivos. Luego uso merge para obtener uno data.frame.

FileNames <- list.files(path=".../tempDataFolder/") 
FirstFile <- read.csv(file=paste(".../tempDataFolder/", FileNames[1], sep=""), 
      header=T, na.strings="NULL") 
SecondFile <- read.csv(file=paste(".../tempDataFolder/", FileNames[2], sep=""), 
       header=T, na.strings="NULL") 
dataMerge <- merge(FirstFile, SecondFile, by=c("COUNTRYNAME", "COUNTRYCODE", "Year"), 
      all=T) 

Ahora uso un bucle for para obtener todos los .csv archivos restantes y merge ellos en el ya existente data.frame:

for(i in 3:length(FileNames)){ 
ReadInMerge <- read.csv(file=paste(".../tempDataFolder/", FileNames[i], sep=""), 
       header=T, na.strings="NULL") 
dataMerge <- merge(dataMerge, ReadInMerge, by=c("COUNTRYNAME", "COUNTRYCODE", "Year"), 
      all=T) 
} 

A pesar de que funciona bien me preguntaba si hay una mayor manera elegante de hacer el trabajo?

Respuesta

37

Es posible que desee mirar de cerca related question on stackoverflow.

me acercaría esto en dos pasos: importar todos los datos (con plyr), y luego fusionar juntos:

filenames <- list.files(path=".../tempDataFolder/", full.names=TRUE) 
library(plyr) 
import.list <- llply(filenames, read.csv) 

Eso le dará una lista de todos los archivos que ahora tiene que fusionar . Hay muchas maneras de hacer esto, pero aquí es uno de los enfoques (con Reduce):

data <- Reduce(function(x, y) merge(x, y, all=T, 
    by=c("COUNTRYNAME", "COUNTRYCODE", "Year")), import.list, accumulate=F) 

Alternativamente, usted puede hacer esto con el paquete reshape si no se siente cómodo con Reduce:

library(reshape) 
data <- merge_recurse(import.list) 
+1

vale la pena notar que se puede obtener toda la XX ing fusionada, con una columna '.id' adicional que contiene nombres de archivos al llamar a' ldply' en lugar de 'llply'. La llamada 'Reduce' o' merge' no es necesaria. – CharlesB

1

Si no me equivoco, un cambio bastante simple podría eliminar la 3:length(FileNames) kludge:

FileNames <- list.files(path=".../tempDataFolder/", full.names=TRUE) 
dataMerge <- data.frame() 
for(f in FileNames){ 
    ReadInMerge <- read.csv(file=f, header=T, na.strings="NULL") 
    dataMerge <- merge(dataMerge, ReadInMerge, 
       by=c("COUNTRYNAME", "COUNTRYCODE", "Year"), all=T) 
} 
+0

@ken: dado que 'dataMerge' es un' data.frame' vacío, la función 'merge()' no puede encontrar un identificador común en el primer bucle 'for'. si asigno, por ejemplo, el primer archivo a 'dataMerge', me devuelve a mi idea inicial. – mropa

+0

Lo siento, debería haberlo intentado primero. Estaba pensando en rbind(), en el que un marco de datos vacío se trata como si las columnas requeridas estuvieran presentes pero vacías. –

Cuestiones relacionadas