Слияние нескольких 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)
}