3

我有一个清单data.frames。在我想通过分组 ( z) 拆分的每个 data.frame 中运行一个函数,将结果重新组合在一起,然后将嵌套的所有结果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在第二个lapply等中进行垃圾处理,以尝试减少内存使用并加快速度?在这种情况下foo喜欢矩阵,所以data.table不会是我的答案。在其他方面foo,我将需要所有w,而班级将需要成为data.frame

4

2 回答 2

9

Try something like this:

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

If you want x and y to show up in your final data.frame, replace summarize with transform. Also, looking at your foo usage, you might have to replace (x, y) with cbind(x, y).

Also, I would recommend you profile your code. In the end, foo might be what is slowing you down, not the split/combine part.

于 2013-01-31T12:22:47.007 回答
6

你为什么不使用ddplyand llplyfromplyr而只是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每个时间都包含在 的每个元素中。然后,在此范围内,我们想拆分。由于输入是a并且输出也应该是 a我们使用第二个参数来分割 by 。在这里,您进行计算,返回您想要的任何内容(在这种情况下)。返回为.qdata.framelistzqdata.framedata.frameddply.(z)zcolSumsldplydata.frame

Data.table解决方案:另一种快速data.table解决方案是在组合上使用 a 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"]
于 2013-01-31T12:12:59.953 回答