使用.BY,.GRP或其他方法添加data.table

时间:2017-07-05 20:39:52

标签: r 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]     

我想这应该是一种较短的写作方式。

4 个答案:

答案 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]