R语言使用foreach包并行优化嵌套for循环并存储结果到dataframe
问题根因
- 原生R的for循环默认仅返回最后一次迭代的计算结果,你内层的两层for循环仅会将最后一组
i,j的结果返回给外层foreach做合并,无法输出全量计算值 - 嵌套foreach的
%:%操作符不需要搭配额外花括号,且多层迭代的.combine参数需要匹配返回值结构 - 函数调用时参数名写错:你定义的函数参数是
repeats,实际调用时写成了R的关键字repeat,会触发语法报错
正确实现方案
这里提供两种可直接运行的写法,最终输出都是符合你要求的dataframe:
方案1:三层迭代全用foreach嵌套(推荐,并行效率更高)
library(foreach) library(doParallel) # 初始化集群 cl <- makeCluster(2) registerDoParallel(cl) df <- data.frame(x=sample(10), y=sample(10), z = sample(10)) repeats <- 2 FUN <- function(df, repeats) { # %:% 用来拼接多层foreach迭代器,不需要加花括号 foreach(k=1:repeats, .combine = 'rbind', .multicombine = TRUE) %:% foreach(i=1:nrow(df), .combine = 'rbind', .multicombine = TRUE) %:% foreach(j=1:ncol(df), .combine = 'rbind', .multicombine = TRUE) %dopar% { data.frame(k=k ,i=i ,j=j , value=df[i, 1] * j ) } } # 注意参数名是repeats,不是R关键字repeat result <- FUN(df, repeats) stopCluster(cl) # 查看结果 head(result)
方案2:保留内层for循环,手动收集结果后返回
如果你不想把内层都改成foreach,可以在内层for循环里把结果存在临时列表里,最后统一返回给外层foreach合并:
FUN <- function(df, repeats) { foreach(k=1:repeats, .combine = 'rbind', .multicombine = TRUE) %dopar% { # 初始化临时列表存内层循环的所有结果 tmp_res <- list() idx <- 1 for(i in 1:nrow(df)) { for(j in 1:ncol(df)) { tmp_res[[idx]] <- data.frame(k=k ,i=i ,j=j , value=df[i, 1] * j ) idx <- idx + 1 } } # 把内层所有结果合并后返回给外层foreach do.call('rbind', tmp_res) } }
补充注意事项
- 如果在Windows系统运行时提示找不到
df对象,可以在最外层foreach的参数里加.export = "df",手动把变量导出到并行集群节点 - 计算逻辑简单的场景下,并行的开销可能比串行还高,实际使用时建议先拿小样本测试效率再全量运行
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

