通常,我使用函数形式`:=`()
来计算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
答案 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)