从函数返回多个输出创建聚合输出data.table

KAE*_*KAE 3 group-by aggregate r data.table

我正在努力解决我遇到的一个特定问题,并且我已经搜索了stackoverflow并找到了接近但不完全符合我想要的示例.最接近的例子就在这里

这篇文章(这里)也接近但我不能让我的多输出函数与list()一起使用

我想要做的是创建具有按键分组的聚合值(min,max,mean,MyFunc)的表.我还有一些复杂的函数可以返回多个输出.我可以返回单个输出但这意味着多次运行复杂功能并且需要太长时间.

使用Matt Dowle在这篇文章中的例子了一些改变......

x <- data.table(a=1:3,b=1:6)[]
   a b
1: 1 1
2: 2 2
3: 3 3
4: 1 4
5: 2 5
6: 3 6
Run Code Online (Sandbox Code Playgroud)

这是我想要的输出类型.聚合表(此处仅包含均值和总和)

agg.dt <- x[ , list(mean=mean(b), sum=sum(b)), by=a][]
   a mean sum
1: 1  2.5   5
2: 2  3.5   7
3: 3  4.5   9
Run Code Online (Sandbox Code Playgroud)

此示例函数f返回3个输出.我的真正功能要复杂得多,而且成分也不能像这样分开.

f <- function(x) {list(length(x), min(x), max(x))}
Run Code Online (Sandbox Code Playgroud)

Matt Dowle对之前帖子的建议很有效,但不生成和聚合表,而是将聚合添加到主表中(在其他情况下也非常有用)

x[, c("length","min", "max"):= f(b), by=a][]
   a b length min max
1: 1 1      2   1   4
2: 2 2      2   2   5
3: 3 3      2   3   6
4: 1 4      2   1   4
5: 2 5      2   2   5
6: 3 6      2   3   6
Run Code Online (Sandbox Code Playgroud)

我真正想做的事情(如果可能的话)就是这样的......

agg.dt <- x[ , list(mean=mean(b)
                       , sum=sum(b)
                       , c("length","min", "max") = f(b)
), by=a]
Run Code Online (Sandbox Code Playgroud)

并返回一个看起来像这样的聚合表...

     a mean sum length min max
1: 1  2.5   5           2   1   4
2: 2  3.5   7           2   2   5
3: 3  4.5   9           2   3   6
Run Code Online (Sandbox Code Playgroud)

我真的只能看到一个解决方案,这是一个两阶段的过程,并将表合并/连接在一起?

Rol*_*and 5

library(data.table)
x <- data.table(a=1:3,b=1:6)
#have the function return a named list
f <- function(x) {list(length=length(x), 
                       min=min(x), 
                       max=max(x))}

# c can combine lists
# c(vector, vector, 3-list) is a 5-list
agg.dt <- x[ , c(mean=mean(b),
                 sum=sum(b),
                 f(b)), 
            by=a]

#   a mean sum length min max
#1: 1  2.5   5      2   1   4
#2: 2  3.5   7      2   2   5
#3: 3  4.5   9      2   3   6
Run Code Online (Sandbox Code Playgroud)

或者,从中删除名称f()以节省为每个组创建相同名称的时间和成本:

f <- function(x) {list(length(x), 
                       min(x), 
                       max(x))}

agg.dt <- x[ , c(mean(b),
                 sum(b),
                 f(b)),
            by=a]

setnames(agg.dt, c("a", "mean","sum","length", "min", "max"))
Run Code Online (Sandbox Code Playgroud)

这个后来的名字 - 然后把它们放回去(当你有很多小组的速度时)你不会进入内部f().f()可能会返回任何内容,因此更难以data.table自动优化.

还要提一下,base::list()不再复制命名输入,如R 3.1.因此,函数f()执行一些复杂步骤然后list()在末尾返回局部变量的常见R语言现在应该更快.