Слияние нескольких data.frames в один data.frame с циклом

Я пытаюсь merge несколько data.frames в один data.frame. Поскольку у меня есть целый список файлов, я пытаюсь сделать это с помощью структуры цикла.

Пока петлевой подход работает отлично. Однако, это выглядит довольно неэффективно, и мне интересно, есть ли более быстрый и легкий подход.

Вот сценарий: У меня есть каталог с несколькими .csv файлами. Каждый файл содержит тот же идентификатор, который может использоваться как переменная слияния. Поскольку файлы довольно большие по размеру, я думал читать каждый файл по одному в R вместо того, чтобы сразу читать все файлы. Поэтому я получаю все файлы каталога с list.files и читаю в первых двух файлах. Впоследствии я использую merge, чтобы получить один 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)

Теперь я использую цикл for, чтобы получить все оставшиеся файлы .csv и merge их в уже существующую 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)
}

Несмотря на то, что это работает отлично, мне было интересно, есть ли более элегантный способ выполнить работу?

Ответ 1

Вы можете посмотреть близкий вопрос fooobar.com/questions/32881/....

Я бы применил это в два этапа: импортировать все данные (с помощью plyr), а затем объединить их:

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

Это даст вам список всех файлов, которые вам теперь нужно объединить. Существует много способов сделать это, но здесь один подход (с Reduce):

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

В качестве альтернативы вы можете сделать это с помощью пакета reshape, если вам не нравится Reduce:

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

Ответ 2

Если я не ошибаюсь, довольно простое изменение может устранить 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)
}