data.table:查找每个组的子集的最小值

时间:2018-12-05 14:35:55

标签: r data.table

如果A,B和C是data.table,dt中的列,我想做的是:创建一个新列(D),这是C中每个组的最小值,经过过滤后只考虑组中B为真的行。到目前为止,我所拥有的是...

dt[, D := min(A[B == TRUE]), by = C]

这行得通,我得到了我想要的结果,但是它非常慢(我的数据集有几百万行)。有更快,更优雅的方法吗?我只对使用data.table的结果感兴趣,请不要使用dplyr :)

2 个答案:

答案 0 :(得分:1)

还有另一种方法,该方法是在过滤后为每个组计算SELECT DISTINCT `submodel` from `goods` ,然后执行 update join 。缺少的组将设置为min(),从而避免了从整数到双精度的类型转换。

NA
# dummy data
dt <- data.table(A = rep(1:3, 3),
                 B = c(rep(c(FALSE, TRUE, TRUE), 2), rep(FALSE, 3)),
                 C = 10L * rep(1:3, each = 3))
dt[, A := A + C]
dt
    A     B  C
1: 11 FALSE 10
2: 12  TRUE 10
3: 13  TRUE 10
4: 21 FALSE 20
5: 22  TRUE 20
6: 23  TRUE 20
7: 31 FALSE 30
8: 32 FALSE 30
9: 33 FALSE 30
# all variables are integer or logical
str(dt)
Classes ‘data.table’ and 'data.frame':    9 obs. of  3 variables:
 $ A: int  11 12 13 21 22 23 31 32 33
 $ B: logi  FALSE TRUE TRUE FALSE TRUE TRUE ...
 $ C: int  10 10 10 20 20 20 30 30 30
 - attr(*, ".internal.selfref")=<externalptr>
dt[dt[(B), min(A), by = C], on = "C", D := V1][]
    A     B  C  D
1: 11 FALSE 10 12
2: 12  TRUE 10 12
3: 13  TRUE 10 12
4: 21 FALSE 20 22
5: 22  TRUE 20 22
6: 23  TRUE 20 22
7: 31 FALSE 30 NA
8: 32 FALSE 30 NA
9: 33 FALSE 30 NA
# all variables are still integer or logical
str(dt)

表达式

Classes ‘data.table’ and 'data.frame':    9 obs. of  4 variables:
 $ A: int  11 12 13 21 22 23 31 32 33
 $ B: logi  FALSE TRUE TRUE FALSE TRUE TRUE ...
 $ C: int  10 10 10 20 20 20 30 30 30
 $ D: int  12 12 12 22 22 22 NA NA NA
 - attr(*, ".internal.selfref")=<externalptr>

按组返回最小值(如果有)

dt[(B), min(A), by = C]

注意事项:我并不是说这比OP的方法要快。由于缺乏可重现的示例,我无法对其进行测试,该示例可以按问题大小进行缩放以进行基准测试。

答案 1 :(得分:0)

我最终将列A转换为数值类型(从整数),以便空组返回最小值NA,然后使用pmin.int()代替min()。事实证明,这比我原来的方法快4倍!