在一个语句中进行多个 data.table 赋值是否有性能优势?
Is there a performance advantage to multiple data.table assignments in one statement?
在 data.table
中,以下结果相同:
dt1 <- data.table(iris)
dt1[, Long.Petal := Petal.Length > mean(Petal.Length)]
dt1[, Wide.Petal := Petal.Width > mean(Petal.Width)]
和
dt2 <- data.table(iris)
dt2[, `:=`(
Long.Petal = Petal.Length > mean(Petal.Length),
Wide.Petal = Petal.Width > mean(Petal.Width)
)]
在处理 大型 数据集时,后一种形式是否具有性能优势(在内存或 运行 时间或两者方面)?还是开销很小,只是风格和可读性的问题?
需要考虑的事情是 a) 对 [.data.table
的调用,以及 b) 运行 [.data.table
中的代码。
打了几个电话,应该影响不大。但是,如果您要执行 100 次或 1000 次(例如,使用 for 循环),那么它的性能可能会降低。主要是由于调度时间 [.data.table
。在那种情况下,只要没有分组,set()
是一个更好的选择。
无论如何,这些东西很容易在您的数据集上进行基准测试。调用 Rprof(); <your_code>; Rprof(NULL); summaryRprof()
应该可以了解花费的时间以及大部分时间花在了哪里。
令我惊讶的是,在以下示例中实际上存在不可忽略的性能差异。它不赞成合并分配:
set.seed(42)
dt1 <- data.table(x = rnorm(1e7))
dt2 <- copy(dt1)
library(microbenchmark)
microbenchmark({dt1[, y := x < 0]; dt1[, z := x > 0]},
dt2[,`:=`(
y = x < 0,
z = x > 0
)])
#Unit: milliseconds
# expr min lq mean median uq max neval cld
#{ dt1[, `:=`(y, x < 0)] dt1[, `:=`(z, x > 0)] } 122.6285 124.0237 143.3914 125.2057 146.0050 305.3609 100 a
# dt2[, `:=`(y = x < 0, z = x > 0)] 153.2545 156.5720 208.5669 178.9714 301.8305 359.2821 100 b
all.equal(dt1, dt2)
#[1] TRUE
在 data.table
中,以下结果相同:
dt1 <- data.table(iris)
dt1[, Long.Petal := Petal.Length > mean(Petal.Length)]
dt1[, Wide.Petal := Petal.Width > mean(Petal.Width)]
和
dt2 <- data.table(iris)
dt2[, `:=`(
Long.Petal = Petal.Length > mean(Petal.Length),
Wide.Petal = Petal.Width > mean(Petal.Width)
)]
在处理 大型 数据集时,后一种形式是否具有性能优势(在内存或 运行 时间或两者方面)?还是开销很小,只是风格和可读性的问题?
需要考虑的事情是 a) 对 [.data.table
的调用,以及 b) 运行 [.data.table
中的代码。
打了几个电话,应该影响不大。但是,如果您要执行 100 次或 1000 次(例如,使用 for 循环),那么它的性能可能会降低。主要是由于调度时间 [.data.table
。在那种情况下,只要没有分组,set()
是一个更好的选择。
无论如何,这些东西很容易在您的数据集上进行基准测试。调用 Rprof(); <your_code>; Rprof(NULL); summaryRprof()
应该可以了解花费的时间以及大部分时间花在了哪里。
令我惊讶的是,在以下示例中实际上存在不可忽略的性能差异。它不赞成合并分配:
set.seed(42)
dt1 <- data.table(x = rnorm(1e7))
dt2 <- copy(dt1)
library(microbenchmark)
microbenchmark({dt1[, y := x < 0]; dt1[, z := x > 0]},
dt2[,`:=`(
y = x < 0,
z = x > 0
)])
#Unit: milliseconds
# expr min lq mean median uq max neval cld
#{ dt1[, `:=`(y, x < 0)] dt1[, `:=`(z, x > 0)] } 122.6285 124.0237 143.3914 125.2057 146.0050 305.3609 100 a
# dt2[, `:=`(y = x < 0, z = x > 0)] 153.2545 156.5720 208.5669 178.9714 301.8305 359.2821 100 b
all.equal(dt1, dt2)
#[1] TRUE