【问题标题】:Is it possible to operate on the aggregated dcast values?是否可以对聚合的 dcast 值进行操作?
【发布时间】:2019-05-30 23:12:53
【问题描述】:

dcast.data.table 具有聚合多个 value.var 的功能。是否可以以某种方式引用正在创建的聚合值,然后在 fun 中执行操作?

这会创建 4 个变量

DT = data.table(x=sample(5,20,TRUE), y=sample(2,20,TRUE),
                z=sample(letters[1:2], 20,TRUE), d1 = runif(20), d2=1L)

> head(DT)
   x y z        d1 d2
1: 3 2 a 0.6166590  1
2: 3 1 a 0.1891611  1
3: 5 2 a 0.3061658  1
4: 3 1 a 0.7233832  1
5: 2 1 b 0.6799675  1
6: 2 1 b 0.5144392  1

dcast(DT, x + y ~ z, fun=sum, value.var=c("d1", "d2"))

   x y      d1_a      d1_b d2_a d2_b
1: 1 1 1.0400277 0.3835004    2    1
2: 2 1 0.7032111 1.3713884    1    2
3: 3 1 0.9759893 2.0853103    1    3
4: 3 2 0.5210792 0.0000000    1    0
5: 4 1 1.0971931 0.4417819    2    1
6: 4 2 0.5009533 0.0000000    1    0
7: 5 1 0.9372943 0.0000000    4    0
8: 5 2 0.7671728 0.0000000    1    0

并且可以在第二步中对聚合值进行操作

dcast(DT, x + y ~ z, fun=sum, value.var=c("d1", "d2"))[,.(div1 = d1_a/d2_a
                                                          ,div2 = d1_b/d2_b)]

        div1      div2
1: 0.5200139 0.3835004
2: 0.7032111 0.6856942
3: 0.9759893 0.6951034
4: 0.5210792       NaN
5: 0.5485965 0.4417819
6: 0.5009533       NaN
7: 0.2343236       NaN
8: 0.7671728       NaN

【问题讨论】:

    标签: r data.table dcast


    【解决方案1】:

    这有点令人费解, 但是对于这个问题,我认为您可以执行以下操作:

    zs <- unique(DT$z)
    
    sum_div <- function(dt) {
      ans <- dt[, .(div = sum(d1) / sum(d2)), by = .(z)]
      split(ans$div, factor(ans$z, levels = zs), drop = FALSE)
    }
    
    DT[, sum_div(.SD), by = .(x, y), .SDcols = c("z", "d1", "d2")]
    

    发生的情况是.SD 最终具有.SDcols 中指定的 3 列, 但对于xy 值的可能组合,有不同的子集。 然后,sum_div 仅在该子集上执行您想要的操作, 和splits 将结果返回一个列表,以便z 的每个可能值在最终的data.table 中都有自己的列。

    为了每次获得相同数量的列表元素,请务必执行factor(ans$z, levels = zs)data.table 预计); 通过指定我们期望有多少levels, 如果level 没有值,split 将返回一个空向量, 但它肯定会为每个人返回一些东西。

    请注意,您可以通过以下方式实现相同的效果:

    dcast(DT[, .(div = sum(d1) / sum(d2)), by = .(x, y, z)], x + y ~ z, value.var = "div")
    

    我不确定你是否通过一步完成所有事情来获得相当大的性能。

    编辑:你可能不会:

    library(data.table)
    library(microbenchmark)
    
    n <- 2e5
    DT = data.table(x = sample(5L, n, TRUE),
                    y = sample(3L, n, TRUE),
                    z = sample(letters[1:2], n, TRUE),
                    d1 = runif(n),
                    d2 = 1L)
    
    zs <- sort(unique(DT$z))
    
    sum_div <- function(dt) {
      ans <- dt[, .(div = sum(d1) / sum(d2)), by = .(z)]
      split(ans$div, factor(ans$z, levels = zs), drop = FALSE)
    }
    
    microbenchmark(
      one = DT[, sum_div(.SD), keyby = .(x, y), .SDcols = c("z", "d1", "d2")],
      two = dcast(DT[, .(div = sum(d1) / sum(d2)), by = .(x, y, z)], x + y ~ z, value.var = "div"),
      times = 10L
    )
    Unit: milliseconds
     expr      min       lq     mean   median       uq      max neval
      one 24.37323 25.74273 26.72413 25.99279 26.62943 34.40309    10
      two 11.31050 11.91650 12.66345 12.51094 13.01364 15.35549    10
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-10
      • 2021-10-29
      • 2019-10-20
      • 1970-01-01
      • 2016-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多