嵌套lapply性能,如何优化?

时间:2013-01-31 11:56:56

标签: r list lapply

我有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

2 个答案:

答案 0 :(得分:9)

尝试这样的事情:

ldply(alist, ddply, "z", summarize, xy.foo = foo(x, y))

如果您希望xy显示在最终的data.frame中,请将summarize替换为transform。另外,查看foo用法,您可能需要将(x, y)替换为cbind(x, y)

此外,我建议您分析您的代码。最后,foo可能会减慢你的速度,而不是分裂/组合部分。

答案 1 :(得分:6)

为什么不使用ddply中的llplyplyr,而只使用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.framedata.frame,输出也应该是ddply,我们使用.(z),第二个参数zcolSums拆分}。在这里,您进行计算,返回您想要的任何内容(在这种情况下为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}}