改进在向量上应用函数并按列分组的处理时间 - R

问题描述 投票:0回答:1

我正在尝试对 data.table 列应用函数,并按列值分组。 我正在使用 lapply 函数,但我的脚本非常慢。

为了提供一些背景信息,我正在研究概率值:

  • 首先,我将每个“id”的每组 5 个概率值乘以一个随机值
  • 然后,我进行以下计算,按变量“group_1”和“group_2”分组:PD_3_N=1-PROD(1-PD_2_N)

这是一个带有虚拟值的可重现示例:

###########
# Dummy data
set.seed(99)
n_col <- 4
size <- 3e6
num_group2 <- 10
vec_1 <- paste0("PD_1_N", (0:n_col))
vec_2 <- paste0("PD_2_N", (0:n_col))
vec_3 <- paste0("PD_3_N", (0:n_col))
id <- rep(seq(1, size, 1), num_group2)
group_1 <- rep(sample(seq(1, size, 1), size=size, replace=TRUE), num_group2)
group_2 <- sort(rep(seq(1, num_group2, 1), size))
factor <- runif(size*num_group2, 0.5, 4)
data <- data.table(id, group_1, group_2, factor)
data[, vec_1] <- data.table(rep(runif(size, 0, 0.5), num_group2), 
                            rep(runif(size, 0, 0.5), num_group2), 
                            rep(runif(size, 0, 0.5), num_group2), 
                            rep(runif(size, 0, 0.5), num_group2), 
                            rep(runif(size, 0, 0.5), num_group2))
###############
# lapply step 1
t <- Sys.time()
data[, (vec_2) := lapply(.SD, function(x) pmin(1, factor*x)), .SDcols=vec_1]
Sys.time() - t

###############
# lapply step 2
t <- Sys.time()
data[, (vec_3) := lapply(.SD, function(x) 1 - prod((1 - x))), 
     by=c("group_1", "group_2"), .SDcols=vec_2]
Sys.time() - t

######################
# test: 2 steps in one
t <- Sys.time()
data[, (vec_3) := lapply(.SD, function(x) 1 - prod((1 - pmin(1, factor*x)))), 
     by=c("group_1", "group_2"), .SDcols=vec_1]
Sys.time() - t
# end test
  • 第 1 步相当快:大约 1 秒
  • 第2步相当慢:大约1.9分钟

有没有办法提高第2步的处理时间? 我还感到惊讶的是,当我尝试将这 2 个步骤合并到一行独特的代码中时,它实际上要慢得多,大约 10 分钟(请参阅上面代码中的“测试:2 个步骤合二为一”)。

r performance data.table query-optimization lapply
1个回答
0
投票

缓慢的部分似乎是分组的

1 - x
。尝试将其移出分组计算:

t <- Sys.time()
data[, (vec_3) := lapply(.SD, function(x) 1 - x), .SDcols = vec_2]
data[, (vec_3) := lapply(.SD, prod), by = c("group_1", "group_2"), .SDcols = vec_3]
data[, (vec_3) := lapply(.SD, function(x) 1 - x), .SDcols = vec_3]
Sys.time() - t
© www.soinside.com 2019 - 2024. All rights reserved.