Функция R, которая перебирает data.frame, открывает / объединяет файлы и возвращает другой фрейм данных. - PullRequest
1 голос
/ 06 января 2012

Я хотел бы знать, как решить следующую проблему, используя функции более высокого порядка, такие как ddply, ldply, dlply, и избегать использования проблемных циклов for.

Проблема: у меня есть файл .csv, представляющий набор данных, загруженный в data.frame, где каждая строка содержит путь к каталогу, где в файлах хранится больше информации.Я хочу использовать информацию каталога в datas.frame, чтобы открыть файлы ("file1.txt", "file2.txt") в этом каталоге, объединить их, а затем объединить объединенные файлы из каждой записи в один большой кадр данных.что-то вроде этого: df =

entryName,dir
1,/home/guest/data/entry1
2,/home/guest/data/entry2
3,/home/guest/data/entry3
4,/home/guest/data/entry4

, что я хотел бы сделать, это применить функцию к кадру данных, который принимает каталог, добавляет пару имен файлов "file1.txt", "file.txt", затем объединяет два файла вместе на основе заданного поля.

для примера file1.txt может быть:

entry,subEntry,value
1,A,2
1,B,3
1,C,4
1,D,5
1,E,3
1,F,3

для примера file2.txt может быть:

entry,subEntry,value
1,A,8
1,B,7
1,C,8
1,D,9
1,E,8
1,F,7

вывод будет выглядеть примерно так:

entryName,subEntry,valueFromFile1,valueFromFile2
1,A,2,8
1,B,3,7
1,C,4,8
1,D,5,9
1,E,3,8
1,F,3,7
2,A,4,8
2,B,5,9
2,C,6,7
2,D,3,7
2,E,6,8
2,F,5,9

Сейчас я использую цикл for, но по понятным причинам хотел бы использовать функцию более высокого порядка.Вот что у меня есть:

allCombined <- data.frame()
df <- read.csv(file="allDataEntries.csv",header=true) 
numberOfEntries = <- dim(df)[1]

for(i in 1:numberOfEntries){ 
  dir <- df$dir[i]
  file1String <- paste(dir,"/file1.txt",sep='') 
  file2String <- paste(dir,"/file2.txt",sep='')
  file1.df <- read.csv(file=file1String,header=TRUE)
  file2.df <- read.csv(file=file2String,header=TRUE)
  localMerged <- merge(file1.df,file2.df, by="value")
  allCombined <- rbind(allCombined,localMerged) 
} 
#rest of my analysis...

Ответы [ 2 ]

2 голосов
/ 06 января 2012

Вот один из способов сделать это.Идея состоит в том, чтобы создать список с содержимым всех файлов, а затем использовать Reduce, чтобы объединить их последовательно, используя общие столбцы entry и subEntry.

# READ DIRECTORIES, FILES AND ENTRIES
dirs    <- read.csv(file = "allDataEntries.csv", header = TRUE, as.is = TRUE)$dir
files   <- as.vector(outer(dirs, c('file.txt', 'file2.txt'), 'file.path'))
entries <- lapply(files, 'read.csv', header = TRUE)

# APPLY CUSTOM MERGE FUNCTION TO COMBINE ENTRIES
merge_by <- function(x, y){
  merge(x, y, by = c('entry', 'subEntry'))
}
Reduce('merge_by', entries)
0 голосов
/ 06 января 2012

Я не проверял это, но похоже, что оно должно работать.Анонимная функция берет одну строку из df, считывает два связанных файла и объединяет их по значению.Использование ddply возьмет эти фреймы данных и сделает из них один фрейм с помощью rbind ing (поскольку запрошенный вывод является фреймом данных).Предполагается, что entryName не повторяется в df.Если это так, вместо этого вы можете добавить уникальную строку в группу.

ddply(df, .(entryName), function(DF) {
  dir <- df$dir
  file1String <- paste(dir,"/file1.txt",sep='') 
  file2String <- paste(dir,"/file2.txt",sep='')
  file1.df <- read.csv(file=file1String,header=TRUE)
  file2.df <- read.csv(file=file2String,header=TRUE)
  merge(file1.df,file2.df, by="value")
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...