有效地组合几个dcast data.table(共享相同的密钥)

时间:2016-08-10 18:54:12

标签: r data.table dcast

以下是我尝试解决的一个简单问题:我有一个data.table,如下表所示,我尝试使用dcast.data.table函数来计算每个组的进度数,我也有兴趣计算每组成绩median

set.seed(10);
DT = data.table(GROUP = sample(c("a","b","c"),100,replace = T), 
                ADVANCED = sample(c("ADVANCED","DROP"),100,replace = T),
                GRADE = sample(1:10,100, replace=T))

     GROUP ADVANCED GRADE
  1:     b ADVANCED     3
  2:     a ADVANCED     6
  3:     b ADVANCED     7
  4:     c ADVANCED     9

 95:     b     DROP     6
 96:     c ADVANCED     5
 97:     a     DROP    10
 98:     b ADVANCED     1
 99:     c     DROP     6
100:     a     DROP     2
     GROUP ADVANCED GRADE

基本上这是我正在寻找的结果:

result = merge(
  dcast.data.table(DT,.Primitive("~")(GROUP,ADVANCED)),
  dcast.data.table(DT,.Primitive("~")(GROUP,.),
                   value.var="GRADE", 
                   fun.aggregate=median));

setnames(result,".","MEDIAN_GRADE")

   GROUP ADVANCED DROP MEDIAN_GRADE
1:     a       17   19            6
2:     b       20   21            7
3:     c       13   10            6

现在我想知道如何在不制作两个单独的dcast表并最后合并的情况下这样做。我在表格中处理了很多行和列,按键分组是一个瓶颈。我想知道有更好的计算方法吗?

**由于我的第一个问题很模糊,我完全编辑(感谢Frank和Akrun的反馈)。

2 个答案:

答案 0 :(得分:3)

好吧,你可以长篇大论然后重塑:

dcast(DT[, rbind(
  .SD[, .(v = .N), by=.(stat = paste0("n.",ADVANCED))],
  .(stat = "med", v = as.numeric(median(GRADE)))
), by=GROUP], GROUP ~ stat)

   GROUP med n.ADVANCED n.DROP
1:     a   6         17     19
2:     b   7         20     21
3:     c   6         13     10

显然,这仍然涉及大量的手动摆弄。它还要求您的统计信息都是数字的(因为它们在stat之前一起堆叠在dcast列中)。我认为@ akrun的答案中的方法 - 比如DT[, f(...), by=GROUP][dcast(DT, GROUP ~ x), on=GROUP] - 要好得多,只能将dcast限制为只需要它的那些电话。

答案 1 :(得分:2)

更新问题

setnames(dcast(DT, GROUP~ADVANCED, length)[dcast(DT, GROUP~., median),
            on = "GROUP"], ".", "MEDIAN_GRADE")[]
#   GROUP ADVANCED DROP MEDIAN_GRADE
#1:     a       17   19            6
#2:     b       20   21            7
#3:     c       13   10            6

或者更快的方法是按'GROUP'进行分组,得到'{1}}'GRADE',然后加入median on输出

dcast