2010-02-05 6 views
27

Ich versuche merge mehrere in einem data.frame. Da ich eine ganze Liste von Dateien habe, versuche ich es mit einer Schleifenstruktur zu machen.Merge mehrere data.frames in einem data.frame mit einer Schleife

Bisher funktioniert der Loop-Ansatz gut. Es sieht jedoch ziemlich ineffizient aus und ich frage mich, ob es einen schnelleren und einfacheren Ansatz gibt.

Hier ist das Szenario: Ich habe ein Verzeichnis mit mehreren .csv Dateien. Jede Datei enthält denselben Bezeichner, der als Fusionsvariable verwendet werden kann. Da die Dateien ziemlich groß sind, dachte ich, jede Datei einzeln in R zu lesen, anstatt alle Dateien gleichzeitig zu lesen. So bekomme ich alle Dateien des Verzeichnisses mit list.files und lese die ersten beiden Dateien ein. Danach benutze ich merge um eine data.frame zu bekommen.

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) 

Jetzt benutze ich eine for Schleife alle verbleibenden .csv Dateien zu erhalten und merge sie in die bereits bestehende 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) 
} 

Auch wenn es ganz gut funktioniert Ich habe mich gefragt, ob es ein mehr elegante Weise, um den Job zu erledigen?

Antwort

37

Sie können sich die related question on stackoverflow genauer ansehen.

Ich würde dies in zwei Schritten nähern: importieren Sie alle Daten (mit plyr), dann miteinander verschmelzen:

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

, die Ihnen eine Liste aller Dateien, die Sie jetzt zusammen fusionieren müssen . Es gibt viele Möglichkeiten, dies zu tun, aber hier ist ein Ansatz (mit Reduce):

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

Alternativ können Sie dieses mit dem reshape Paket tun können, wenn Sie sich nicht wohl mit Reduce:

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

Es kann sich lohnen, zu bemerken, dass man das ganze th bekommen fusioniert, mit einer zusätzlichen '.id'-Spalte, die Dateinamen enthält, indem' ldply' anstelle von 'llply' aufgerufen wird. Der Aufruf 'Reduzieren' oder 'Zusammenführen' ist dann nicht erforderlich. – CharlesB

1

wenn mich nicht alles täuscht, könnte eine ziemlich einfache Änderung der 3:length(FileNames) kludge beseitigen:

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: Da das 'dataMerge' ein leeres' dat.frame' ist, kann die 'merge() 'Funktion in der ersten' for' Schleife keinen gemeinsamen Bezeichner finden. Wenn ich zB 'dataMerge' die erste Datei zuweiße, bringt mich das irgendwie auf meine ursprüngliche Idee zurück. – mropa

+0

Sorry, ich hätte es zuerst versuchen sollen. Ich habe an rbind() gedacht, bei dem ein leerer Datenrahmen so behandelt wird, als wären die benötigten Spalten vorhanden, aber leer. –

Verwandte Themen