我有data.frames
的列表。在每个data.frame中我想通过分组(z
)运行一个函数,将结果重新组合在一起,然后将嵌套lapply
的所有结果放在一个data.frame中,然后将结果data.frame
列表展平为一个data.frame
。
library(plyr)
df <- data.frame(x = sample(1:200, 30000, replace = TRUE),
y = sample(1:200, 30000, replace = TRUE),
z = sample(LETTERS, 30000, replace = TRUE))
alist <- list(df,df,df) # longer in real life
answer <- lapply(alist, function(q) {
a <- split(q,q$z)
result.1 <- lapply(a, function(w) {
neww <- cbind(w[,1],w[,2])
result.2 <- colSums(neww)
})
ldply(result.1)
})
# cor(neww) can actually be a variey of foos I just use cor() for easy reproducibility
ldply(answer)
这有一些非常严重的内存使用,也很慢。感谢@Andrie,我知道如何在开始之前清理我的工作区:
rm(list=setdiff(ls(), "alist"))
但有没有办法在第二个w
等中修改我的方法,如junking lapply
,以尝试减少内存使用并加快速度?在这种情况下,foo
喜欢矩阵,因此data.table
不是我的答案。在其他foo
中,我需要所有w
,而课程必须是data.frame
答案 0 :(得分:9)
尝试这样的事情:
ldply(alist, ddply, "z", summarize, xy.foo = foo(x, y))
如果您希望x
和y
显示在最终的data.frame中,请将summarize
替换为transform
。另外,查看foo
用法,您可能需要将(x, y)
替换为cbind(x, y)
。
此外,我建议您分析您的代码。最后,foo
可能会减慢你的速度,而不是分裂/组合部分。
答案 1 :(得分:6)
为什么不使用ddply
中的llply
和plyr
,而只使用ldply
??
# Note: @Flodel has a very nice, simple one-line plyr solution
# Please use that.
out <- ldply(alist, function(q) {
ddply(q, .(z), function(w) {
neww <- w[, -3]
result.2 <- colSums(neww) # dummy function
})
})
第一个ldply
逐个传递列表alist
的元素。因此q
每次data.frame
都包含list
的每个元素中的z
。然后,在此范围内,我们希望按q
分割。由于输入data.frame
是data.frame
,输出也应该是ddply
,我们使用.(z)
,第二个参数z
将colSums
拆分}。在这里,您进行计算,返回您想要的任何内容(在这种情况下为ldply
)。 data.frame
返回Data.table
。
data.table
解决方案:替代快速解决方案是在合并data.frame
上使用require(data.table)
# for creating a group
group <- vapply(alist, nrow, integer(1))
dt <- data.table(do.call(rbind, alist))
# create group
dt[ , grp := rep(1:3, group)]
setkey(dt, "grp", "z")
# call your function (here column means)
dt[, lapply(.SD, mean), by="grp,z"]
# or if its correlation
dt[, list(cor_x_y = cor(x,y)), by="grp,z"]
,这可以通过以下方式实现(@Roland提到的内容)在他的评论中也是如此):
{{1}}