9

使用data.table包,是否可以汇总未出现在输入中的变量的数据保留组合?

使用plyr包,我知道如何使用 .drop 参数执行此操作,例如:

require(plyr)
df <- data.frame(categories = c(rep("A",3), rep("B",3), rep("C",3)), groups = c(rep(c("X", "Y"),4), "Z"), values = rep(1, 9))

df1 <- ddply(df, c("categories","groups"), .drop = F, summarise, sum = sum(values))

输出:

 categories groups sum
1          A      X   2
2          A      Y   1
3          A      Z   0
4          B      X   1
5          B      Y   2
6          B      Z   0
7          C      X   1
8          C      Y   1
9          C      Z   1

在这种情况下,即使总和为 0,我也会保留所有组/类别组合。

4

1 回答 1

9

好问题。这里有两种方法。他们都使用by-without-by。

DT = as.data.table(df)
setkey(DT,categories,groups)
DT[CJ(unique(categories),unique(groups)), sum(values,na.rm=TRUE)]

   categories groups V1
1:          A      X  2
2:          A      Y  1
3:          A      Z  0
4:          B      X  1
5:          B      Y  2
6:          B      Z  0
7:          C      X  1
8:          C      Y  1
9:          C      Z  1

其中CJ代表交叉连接,请参阅?CJ。by-without-by 仅表示在每行加入的j每个组上执行。i

诚然,乍一看它看起来很棘手。这个想法是,如果您有一个已知的组子集,则此语法比将所有内容分组然后仅从中选择您需要的结果更快。但是在这种情况下,您无论如何都想要所有东西,所以除了能够查找数据中不存在的组(您无法使用by)之外,没有太多优势。

另一种方法是by首先照常,然后将CJ()结果加入:

DT[,sum(values),keyby='categories,groups'][CJ(unique(categories),unique(groups))]
   categories groups V1
1:          A      X  2
2:          A      Y  1
3:          A      Z NA
4:          B      X  1
5:          B      Y  2
6:          B      Z NA
7:          C      X  1
8:          C      Y  1
9:          C      Z  1

但随后你会得到 NA 而不是所需的 0。set()如果需要,可以使用这些替换。第二种方法可能更快,因为这两个unique调用的输入要小得多。

如果您经常这样做,这两种方法都可以包装成小的辅助函数。

于 2013-01-23T18:16:48.807 回答