在%dopar%中使用do.call()出现函数参数未找到的问题求助
解决方法
方法1:直接使用函数对象而非字符名(推荐)
修改主脚本,先在主环境加载方法脚本,将方法存储为函数列表,彻底避免do.call的环境查找问题:
library(foreach) library(doParallel) # 先在主环境加载方法脚本,获取函数对象 source('methods.R') # 将方法存为命名列表,方便后续索引结果 methods <- list(method1 = method1, method2 = method2) cl <- makeCluster(4) registerDoParallel(cl) # 把函数对象直接传递给所有集群节点 clusterExport(cl, c('method1', 'method2')) foreach(sim = seq(100)) %dopar% { data <- *Data generation* # 替换为你的数据生成代码 results <- vector(mode='list', length=0) for (method_name in names(methods)){ # 直接调用函数,无需do.call RES <- methods[[method_name]](data) results[[method_name]] <- RES } results # 必须返回结果,否则foreach不会收集输出 } stopCluster(cl) # 最后关闭集群释放资源
为什么这样有效?
通过clusterExport将主环境中的函数对象直接传给每个节点,避免了节点环境重新source脚本可能出现的路径问题;同时直接调用函数对象,跳过了do.call对字符函数名的环境查找步骤,确保data作为参数被正确传递到方法内部。
方法2:保留字符名,指定do.call的环境参数
如果坚持使用字符形式的方法名,只需在do.call中显式指定envir参数为当前任务的局部环境,确保参数查找正确:
library(foreach) library(doParallel) methods <- c('method1', 'method2') cl <- makeCluster(4) registerDoParallel(cl) # 建议用绝对路径加载脚本,避免节点工作目录与主进程不一致的问题 clusterEvalQ(cl, source('/你的绝对路径/methods.R')) foreach(sim = seq(100)) %dopar% { data <- *Data generation* results <- vector(mode='list', length=0) for (method in methods){ # 指定envir为当前任务的局部环境 RES <- do.call(method, list(data=data), envir = environment()) results[[method]] <- RES } results } stopCluster(cl)
错误原因解析
原错误是因为do.call默认在调用它的环境的父环境(即集群节点的全局环境)中解析参数,但data是定义在%dopar%块的局部任务环境里。显式指定envir = environment()后,do.call会在当前任务的局部环境中查找并传递data参数,解决找不到对象的问题。
内容的提问来源于stack exchange,提问作者Telmo Pérez Izquierdo
相关产品推荐
相关产品推荐

