为什么:=比`:=`()快?

时间:2019-06-19 11:48:58

标签: r data.table

通常,我使用函数形式`:=`()来计算data.table中的多列,认为这是最有效的方法。但是我最近发现,它比简单地重复使用:=慢。至少在我的计算机上。

我猜想:=的功能形式可能会有一些开销,但这是否是它变慢的全部原因呢?我只是出于好奇而问,以便更好地了解data.table的内部。

library(data.table)


n <- 5000000
dt <- data.table(a = rnorm(n),
                 b = rnorm(n),
                 c = rnorm(n))

dt_a <- copy(dt)

system.time({
  dt_a[, d := a + b]
  dt_a[, e := b + c]
  dt_a[, f := a + c]
})
#>    user  system elapsed 
#>   0.076   0.060   0.136

dt_b <- copy(dt)

system.time({
  dt_b[, `:=`(d = a + b,
              e = b + c,
              f = a + c)]
})
#>    user  system elapsed 
#>   0.096   0.116   0.211

更新:

一个有趣的特性是:=`:=`()之间的时间差是1.5到2的相对值。如果这仅仅是由于函数开销,如某些人建议的那样,会怀疑时差是固定值吗?

library(data.table)


n <- 20000000
dt <- data.table(a = rnorm(n),
                 b = rnorm(n),
                 c = rnorm(n))

dt_a <- copy(dt)

system.time({
  dt_a[, d := a + b]
  dt_a[, e := b + c]
  dt_a[, f := a + c]
})
#>    user  system elapsed 
#>   0.163   0.208   0.371

dt_b <- copy(dt)

system.time({
  dt_b[, `:=`(d = a + b,
              e = b + c,
              f = a + c)]
})
#>    user  system elapsed 
#>   0.284   0.404   0.688

1 个答案:

答案 0 :(得分:2)

一些时间:

bench::mark(
    chaining = DT0[, d := a + b][, e := b + c][, f := a + c],
    assign = DT1[, c("d", "e", "f") := .(a+b, b+c, a+c)],
    assign2 = DT1.1[, `:=` (d, a + b)][, `:=` (e, b + c)][, `:=` (f, a + c)],
    use_set = {
        set(DT2, NULL, "d", DT2[["a"]]+DT2[["b"]])
        set(DT2, NULL, "e", DT2[["b"]]+DT2[["c"]])
        set(DT2, NULL, "f", DT2[["a"]]+DT2[["c"]])
    },
    functional = DT3[, `:=`(d = a + b, e = b + c, f = a + c)]
)

时间和内存使用情况:

  expression     min    mean  median     max `itr/sec` mem_alloc  n_gc n_itr total_time result           memory      time   gc       
  <chr>      <bch:t> <bch:t> <bch:t> <bch:t>     <dbl> <bch:byt> <dbl> <int>   <bch:tm> <list>           <list>      <list> <list>   
1 chaining     180ms   180ms   180ms   180ms      5.54     458MB     1     1      180ms <data.table [20~ <Rprofmem ~ <bch:~ <tibble ~
2 assign       320ms   320ms   320ms   320ms      3.12     916MB     1     1      320ms <data.table [20~ <Rprofmem ~ <bch:~ <tibble ~
3 assign2      188ms   188ms   188ms   188ms      5.33     458MB     1     1      188ms <data.table [20~ <Rprofmem ~ <bch:~ <tibble ~
4 use_set      322ms   323ms   323ms   323ms      3.10     916MB     0     2      645ms <data.table [20~ <Rprofmem ~ <bch:~ <tibble ~
5 functional   331ms   331ms   331ms   331ms      3.02     916MB     1     1      331ms <data.table [20~ <Rprofmem ~ <bch:~ <tibble ~

数据:

library(data.table) #data.table_1.12.2  
set.seed(0L)
n <- 2e7
DT <- data.table(a=rnorm(n), b=rnorm(n), c=rnorm(n))
DT0 <- copy(DT)
DT1 <- copy(DT)
DT1.1 <- copy(DT)
DT2 <- copy(DT)
DT3 <- copy(DT)