在嵌套字段中应用函数时,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(数量级可能会有很大的差异

给TA打赏
共{{data.count}}人
人已打赏
解决方案

mysql数据库中的特殊字符

2022-4-22 2:00:15

解决方案

在grpc中添加记录中间

2022-4-22 2:00:17

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索