在嵌套字段中应用函数时,data.table表现不佳。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在嵌套字段中应用函数时,data.table表现不佳。相关的知识,希望对你有一定的参考价值。
我写了一个函数,将另一个函数应用到data.table的每个嵌套字段中。
n <- 3000
nameslist <- paste0("NAME",1:n)
dt <- data.table(name_var = nameslist
, value_var = rnorm(1e7)
, car_color = c("B","B","B","G","G","G","G"))
dt <- dt[,.(.(.SD)), by = name_var] # nesting dt and finishing toy data creation
transform_value <- function(x, fun, campo, ...) {
x [, match.fun (fun)(get(campo), ...)] }
system.time({
dt[, min_value:=lapply(V1, transform_value, "min", "value_var")
]})
这个函数运行得很正确,速度也很快,在我的机器上大约需要0.36秒 n <- 3000
.
然而,当我做 n <- 500000
(nameslist长度为500,000长),需要217秒!
因此,似乎data.table没有被我在循环中写的代码有效地优化。dt[, min_value:=lapply(V1, transform_value, "min", "value_var")
. 我的看法是,每次data.table进入嵌套循环的每个实例都会有一个开销,但我不确定。
我怎样做才能使它运行得更快?
答案
既然你是通过性能来感兴趣的,你一定要设置一个主键。一旦支付了设置主键的固定成本(这意味着你的行在连续内存插槽中的重新排序),你将体验到显著的收益。
再拿你的例子来说
dt <- data.table(name_var = nameslist
, value_var = rnorm(1e7)
, car_color = c("B","B","B","G","G","G","G"))
dt2 <- data.table::copy(dt)
setkeyv(dt2, c("name_var"))
microbenchmark::microbenchmark(
dt[,.(.(.SD)), by = name_var],
dt2[,.(.(.SD)), by = name_var],
times = 20L
)
Unit: milliseconds
expr min lq mean median uq max neval
dt[, .(.(.SD)), by = name_var] 658.76452 676.22905 706.3578 699.46644 727.8368 793.1192 20
dt2[, .(.(.SD)), by = name_var] 91.62276 92.48002 131.2777 99.15238 135.1332 318.3719 20
就这一步,在我的笔记本上(那速度不快),你看计算时间除以7(数量级可能会有很大的差异
以上是关于在嵌套字段中应用函数时,data.table表现不佳。的主要内容,如果未能解决你的问题,请参考以下文章