使用.BY,.GRP或其他方法添加data.table的多列聚合

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用.BY,.GRP或其他方法添加data.table的多列聚合相关的知识,希望对你有一定的参考价值。

假设我们有这个玩具data.table示例:

temp <- data.table(V=c("A", "B", "C", "D","A"), GR=c(1,1,1,2,2))    
"V" "GR"
 A   1
 B   1
 C   1
 D   2
 A   2

我想在GR定义的每个子集内生成所有带有combn的有序组合,并用它创建一个新的data.table和一个带有分组因子的新列。

例如,对于GR = 1,我们有(A,B),(A,C),(B,C) 对于GR = 2,我们有(D,A)

如果我手动创建结果,那将是

cbind(V=c(1,1,1,2),rbind(t(combn(c("A", "B", "C"),2)),t(combn(c( "D","A"),2))))

1  A  B
1  A  C
1  B  C
2  D  A

但我想用data.table轻松做到这一点。 这两个选项不起作用:

temp[,cbind(rep(.GRP,.N),as.data.frame(t(combn(V,2)))),by=GR]     
temp[,cbind(rep(.BY,.N),as.data.frame(t(combn(V,2)))),by=GR]     

这一项工作,但我不明白为什么。我担心它可以复制整个B矢量而不是正确的值。

temp[,.(GR,as.list(as.data.frame((combn(V,2))))),by=GR]     

我想它应该是一种更短的编写方式。

答案

这有效:

> temp[, {v_comb = combn(V,2); .(v_comb[1,], v_comb[2,])}, by=GR]
   GR V1 V2
1:  1  A  B
2:  1  A  C
3:  1  B  C
4:  2  D  A

一般情况下,我会尽可能避免使用cbind()rep()as.data.frame()t()在data.table中进行所有重塑操作...需要许多试验和错误来找出正确的方法来执行它,并生成代码很难维护。

另一方面,使用代码块{...}提高了代码的可读性。

另一答案

这使用data.table,但不是全部在[]内使用.BY或.GRP。

library(data.table)
temp <- data.table(V=c("A", "B", "C", "D","A"), GR=c(1,1,1,2,2)) 

tempfunc <- function(x){ 
  dat <- as.data.table(t(combn(temp[GR == x, V], 2)))
  dat[, GR := x]
  setcolorder(dat, c("GR", "V1", "V2"))
  dat[]
}

rbindlist(lapply(unique(temp$GR), tempfunc))

   GR V1 V2
1:  1  A  B
2:  1  A  C
3:  1  B  C
4:  2  D  A
另一答案

如果有一个只有一行的组,例如下面的第6行,这里有另外两种方法也可以使用:

library(data.table)
temp <- data.table(V=c("A", "B", "C", "D","A","E"), GR=c(1,1,1,2,2,3))    
temp
   V GR
1: A  1
2: B  1
3: C  1
4: D  2
5: A  2
6: E  3

Using cominat::combn2

temp[, as.data.table(combinat::combn2(V)), by = GR]
   GR V1 V2
1:  1  A  B
2:  1  A  C
3:  1  B  C
4:  2  D  A

Using a non-equi join

temp[, V := factor(V)][temp, on = .(GR, V < V), .(GR, x.V, i.V), 
                       nomatch = 0L, allow = TRUE]
   GR x.V i.V
1:  1   A   B
2:  1   A   C
3:  1   B   C
4:  2   A   D
另一答案

我有一个解决方案,但它似乎也很复杂。

temp[,do.call(c, apply(t(combn(V,2)), 2, list)),by=GR]

我还发现combn比iterpc或combinat等专用软件包慢10倍

temp[,do.call(c, apply(combn2(V), 2, list)),by=GR]

您还必须先筛选出只有一行的任何组,否则会导致错误。

这是我的最终版本,速度更快,内存更少:

temp[,.(from=rep(V,(.N-1):0),to=V[unlist(sapply(2:.N, seq, .N, simplify = T))]), by=GR] 

以上是关于使用.BY,.GRP或其他方法添加data.table的多列聚合的主要内容,如果未能解决你的问题,请参考以下文章

查找每组其他行的最大值

npm install使用node-pre-grp和node-grp失败

linux用户管理常用命令总结

使用 apache kafka 或 activemq 哪个更好?

在R中的函数内取消引用参数

将GROUP BY / CASE与WHEN或IF一起使用