【发布时间】:2019-08-25 16:03:47
【问题描述】:
我正在处理一个需要并行计算以获得比经典“for 循环”更快的结果的问题。
问题来了:
我需要为列表对象的数据框中包含的 198135 个结果变量生成线性模型。我必须将模型中每个预测变量的所有 beta 值和 p 值存储在数据框中,以及它们的拟合优度度量。
我编写了一个功能性“for 循环”,可以正确完成任务,但完成它需要 35 多个小时。我知道 R 使用的 8 核 CPU 不到 20%,我想全部使用它。问题是我不知道如何在 foreach 循环中转换我的 for 循环以利用并行计算。
这是我的问题的一些小规模示例代码:
library(tidyverse)
library(broom)
## Example data
outcome_list <- list(as.data.frame(cbind(rnorm(32), dataframe_id = c(1))),
as.data.frame(cbind(rnorm(32), dataframe_id = c(2))),
as.data.frame(cbind(rnorm(32), dataframe_id = c(3)))) ## This represents my list of 198135 dataframes
mtcars <- mtcars #I will use the explanatory variables from here
## Below this line is my current solution with a for loop that works fine
x <- list()
results_df <- as.data.frame(cbind(dataframe_id = c(0), intercept = c(0),
b_mpg = c(0), p_mpg = c(0),
b_cyl = c(0), p_cyl = c(0),
p.model = c(0), AIC = c(0),
BIC = c(0)))
for(i in 1:3){
x[[i]] <- lm(outcome_list[[i]]$V1 ~ mtcars$mpg + mtcars$cyl)
gof <- broom::glance(x[[i]])
betas <- broom::tidy(x[[i]])
results_df <- rbind(results_df, c(outcome_list[[i]]$V2[1],
betas$estimate[1],
betas$estimate[2], betas$p.value[2],
betas$estimate[3], betas$p.value[3],
gof$p.value, gof$r.squared, gof$AIC,
gof$BIC))
if(i %% i == 0){
message(paste(i, "of 3")) # To know if my machine has not crashed
x <- list() # To keep RAM clean of useless data
}
gc()
}
results_df <- results_df[-1, ]
使用上面显示的代码,我得到了我需要的结果(具有回归参数的数据框和列表中每个结果变量的拟合优度),但它非常慢,因为我无法使用我的所有计算机电源。
我知道使用“foreach”和“doParallel”包可以更快地解决这个问题,但我仍然不明白 foreach 循环结构背后的逻辑,因为这是我第一次需要处理这么多数据。
PS:我已经尝试了几种使用 foreach 函数的方法,但我没有得到任何结果。我没有写我的 foreach 尝试解决方案,因为我不明白我在做什么。
【问题讨论】:
-
您的代码如此缓慢的部分原因是您在每次迭代时将新元素添加到
x和results_df。这意味着 R 必须随着它们的增长不断重新分配内存。每次循环迭代时只输出新行。
标签: r foreach parallel-processing