我想知道如何使用高阶函数(如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...
答案 0 :(得分:2)
这是一种方法。我们的想法是创建一个包含所有文件内容的列表,然后使用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)
答案 1 :(得分:0)
我没有对此进行过测试,但它似乎应该可行。匿名函数从df
获取单行,读取两个关联文件,并按值将它们合并在一起。使用ddply
将获取这些数据帧并通过rbind
从中生成单个数据帧(因为请求的输出是数据帧)。假设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")
})