使用.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失败