嵌套lapply性能,如何优化?

use*_*502 3 r list lapply

我有一份清单data.frames.在每个data.frame中,我想通过grouping(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)
Run Code Online (Sandbox Code Playgroud)

这有一些非常艰难的内存使用,也很慢.感谢@Andrie,我知道在开始之前如何清理我的工作区:

 rm(list=setdiff(ls(), "alist"))
Run Code Online (Sandbox Code Playgroud)

但有没有办法修改我的方法,如w在第二个lapply等中的junking ,以尝试减少内存使用和加快速度?在这种情况下foo喜欢矩阵,所以data.table不会是我的答案.在其他foos我将需要所有w和类将需要是一个data.frame

flo*_*del 9

尝试这样的事情:

ldply(alist, ddply, "z", summarize, xy.foo = foo(x, y))
Run Code Online (Sandbox Code Playgroud)

如果您想要xy显示在最终的data.frame中,请替换summarizetransform.此外,看着你的foo使用情况,您可能必须更换(x, y)cbind(x, y).

另外,我建议您分析您的代码.最后,foo可能是什么让你失望,而不是分裂/组合部分.


Aru*_*run 6

你为什么不使用ddplyllplyplyr但只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
    })
})
Run Code Online (Sandbox Code Playgroud)

第一个ldply传递列表中的元素alist.q因此每次都data.frame包含在每个元素中list.然后,在这之内,我们想分开z.由于输入是qa data.frame并且输出也应该是data.frame我们使用ddply第二个参数.(z)来分割z.在这里,你进行计算,返回你想要的任何东西(colSums在这种情况下).作为ldply回报data.frame.

Data.table解决方案:一个替代的快速解决方案是使用data.table组合data.frame可以实现如下(@Roland在他的评论中也提到了):

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"]
Run Code Online (Sandbox Code Playgroud)

  • 不是`ldply(llply(...))`就像`ldply(...)`一样,所以你可以节省不必要的处理? (3认同)