data.table:表中所有现有组合的总和

Mar*_*rio 1 group-by r sum data.table

我有一个out像这样的data.table (实际上它要大得多):

out <-      code weights group
        1:    2   0.387      1
        2:    1   0.399      1
        3:    2   1.610      1
        4:    3   1.323      2
        5:    2   0.373      2                                            
        6:    1   0.212      2
        7:    3   0.316      3
        8:    2   0.569      3
        9:    1   0.120      3
       10:    1   0.354      3
Run Code Online (Sandbox Code Playgroud)

它有3组不同的代码(第1列).在组#1中,代码3不出现,而在另一组中出现.

然后,我想对每个组和代码组合的权重求和.我用这个命令实现了这个目的:

sum.dt <- out[,.(sum(weights)), by=list(code,group)][order(-V1)]
Run Code Online (Sandbox Code Playgroud)

这种方法效果很好但它没有组合1和代码3的组合,因为它不在out表中.我希望有所有可能的组合sum.dt,如果在源表中没有出现组合,它应该总和为0,这意味着V1该行在该行中应为0.

知道我怎么能做到这一点?

Jaa*_*aap 6

使用CJ(交叉连接),您可以添加缺少的组合:

library(data.table)
setkey(out, code, group)
out[CJ(code, group, unique = TRUE)
    ][, lapply(.SD, sum), by = .(code, group)
      ][is.na(weights), weights := 0]
Run Code Online (Sandbox Code Playgroud)

得到:

   code group weights
1:    1     1   0.399
2:    1     2   0.212
3:    1     3   0.474
4:    2     1   1.997
5:    2     2   0.373
6:    2     3   0.569
7:    3     1   0.000
8:    3     2   1.323
9:    3     3   0.316
Run Code Online (Sandbox Code Playgroud)

或者xtabs在评论中显示@alexis_laz:

xtabs(weights ~ group + code, out)
Run Code Online (Sandbox Code Playgroud)

这使:

     code
group     1     2     3
    1 0.399 1.997 0.000
    2 0.212 0.373 1.323
    3 0.474 0.569 0.316
Run Code Online (Sandbox Code Playgroud)

如果要在长格式数据框中获取此输出,可以将xtabs代码包装meltreshape2(或data.table)包的函数中:

library(reshape2)
res <- melt(xtabs(weights ~ group + code, out))
Run Code Online (Sandbox Code Playgroud)

这使:

> class(res)
[1] "data.frame"
> res
  group code value
1     1    1 0.399
2     2    1 0.212
3     3    1 0.474
4     1    2 1.997
5     2    2 0.373
6     3    2 0.569
7     1    3 0.000
8     2    3 1.323
9     3    3 0.316
Run Code Online (Sandbox Code Playgroud)

您也可以使用dplyrtidyr的组合来完成此操作:

library(dplyr)
library(tidyr)
out %>%
  complete(code, group, fill = list(weights=0)) %>%
  group_by(code, group) %>% 
  summarise(sum(weights))
Run Code Online (Sandbox Code Playgroud)