假设我们有这个玩具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]
我想这应该是一种较短的写作方式。
答案 0 :(得分:2)
这有效:
Auth::user()
一般情况下,我会尽可能避免使用> 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()
在data.table中进行所有重塑操作...这需要很多试验和错误,以找出正确的方法,并产生非常难以维护的代码。
另一方面,使用代码块t()
可以提高代码的可读性。
答案 1 :(得分:1)
这使用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
答案 2 :(得分:0)
如果有一个只有一行的组,例如下面的第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
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
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
答案 3 :(得分:-1)
我有一个解决方案,但它似乎也很复杂。
In [9]: lb.fit_transform([0, 1, 2, 0, 2, 2])
Out[9]:
array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
[1, 0, 0],
[0, 0, 1],
[0, 0, 1]])
In [10]: lb.fit_transform([0, 1, 9, 0, 9, 9])
Out[10]:
array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
[1, 0, 0],
[0, 0, 1],
[0, 0, 1]])
In [11]: lb.fit_transform(['first', 'second', 'third', 'first', 'third', 'third'])
Out[11]:
array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
[1, 0, 0],
[0, 0, 1],
[0, 0, 1]])
我还发现combn比iterpc或combinat等专业软件包慢10倍
temp[,do.call(c, apply(t(combn(V,2)), 2, list)),by=GR]
您还必须先筛选出只有一行的任何组,否则会导致错误。
这是我的最终版本,速度更快,内存更少:
temp[,do.call(c, apply(combn2(V), 2, list)),by=GR]