data.table中的ddply'drop = FALSE'等价物

时间:2018-03-16 12:54:29

标签: r data.table

使用ddply返回摘要数据的数据框时,如下所示:

new_data <- ddply(data, .(grp1, grp2), function(x){
   val_list <- some_func(x.some_val)
   data.frame(
   val_1 = val_list[1],
   val_2 = val_list[2],
   val_3 = val_list[3]
   )}, .drop=FALSE
)

.drop=FALSE表示我获得grp1grp2组合的行,即使data中没有这些组合。

在使用data.table制作汇总表时,我正在寻找dt[,.(val1=some_func(some_val1, some_val2)), by='grp1,grp2']中的等效功能,因为这将排除不存在的组合。

编辑:更完整的示例

输入:

data = read.csv(text = "
grp1, grp2, some_var1, some_var2
a, x, 3, 1
a, y, 3, 2
a, y, 3, 2
b, x, 3, 2
b, y, 4, 2
b, y, 4, 1 
c, x, 5, 1
c, y, 5, 2 
c, z, 5, 2")

现在假设我想要每组的(some_var1 * some_var2)的平均值以及每个var的总和。

如果我使用ddply:

library(plyr)
new_data <- ddply(data, .(grp1, grp2), function(x){
   data.frame(
   val_1 = mean(x$some_var1 * x$some_var2),
   val_2 = sum(x$some_var1),
   val_3 = sum(x$some_var2)
   )}, .drop=FALSE
)

输出:

grp1, grp2, val_1, val_2, val_3
a, x, 3, 3, 1
a, y, 6, 6, 4
a, z, NA, NA, NA
b, x, 6, 3, 2
b, y, 6, 8, 3
b, z, NA, NA, NA
c, x, 5, 5, 1
c, y, 10, 5, 2
c, z, 10, 5, 2

但是使用data.table这些NA行不会被包含在内,因为原始数据没有grp1grp2的组合。 显然这是一个大规模简化的例子,实际上我使用三个分组变量在更多可能的组中计算它,并返回三个以上的新简单摘要变量。

1 个答案:

答案 0 :(得分:1)

我认为你提到的ddply方法实际上可能是你最好的选择。我提出了另一个解决方案,但我更喜欢ddply,说实话......

我们走了:

f <- function(x, y) {list( mean(x * y), sum(x), sum(y))}

dt[, c("v1", "v2", "v3") := f(some_var1, some_var2), by = list(grp1, grp2)]
dt[, c("some_var1", "some_var2") := NULL]

现在,我们将使用.drop=FALSE通过左连接来模仿merge() - 功能。这里的诀窍是,我们使用grid::expand.grid构建一个左表,其中包含grp1grp2的所有组合:

left_tab <- grid::expand.grid(grp1 = unique(dt$grp1), grp2 = unique(dt$grp2))
merge(left_tab, unique(dt), all.x = TRUE)
#       grp1 grp2 val_1 val_2 val_3
# 1    a    x     3     3     1
# 2    a    y     6     6     4
# 3    a    z    NA    NA    NA
# 4    b    x     6     3     2
# 5    b    y     6     8     3
# 6    b    z    NA    NA    NA
# 7    c    x     5     5     1
# 8    c    y    10     5     2
# 9    c    z    10     5     2