Foreach 循环找不到对象
Foreach loop unable to find object
我正在尝试将 foreach 与并行后端一起使用以加快计算速度(对 {AUCRF} 随机森林进行特征选择的交叉验证,如果这很重要的话)。在这样做的过程中,我需要获得向量的一个子集。向量的名称可以更改,但可以作为字符向量访问。我使用 eval(parse()) 构造(好主意?)来获取向量的一个子集。
示例:
library(parallel)
library(foreach)
library(stats)
#create cluster
clu <- makeCluster(detectCores() - 1)
registerDoParallel(clu, cores = detectCores() - 1)
bar<-c("a","b","c","d")
rab<-c(2,3)
bar.name<-"bar"
#expected output in this example is a list containing ten times
bar[rab]
#or
eval(parse(text=paste(bar.name,"[rab]",sep="")))
foo<-foreach(m = 1:10, .packages = c("stats")) %dopar% {
sink("foreach.txt")
print(bar.name)
print(parse(text=paste(bar.name,"[rab]",sep="")))
print(eval(parse(text=paste(bar.name,"[rab]",sep=""))))
foo.temp<-eval(parse(text=paste(bar.name,"[rab]",sep="")))
return(foo.temp)
}
sink()
stopCluster(clu)
但是我收到以下错误:
Error in { : task 1 failed - "Object 'bar' not found"
我认为每个工作人员都得到一份包含所有对象的工作区副本。知道我做错了什么吗?
这听起来像是一个糟糕的设计。几乎没有必要使用 eval(parse())
.
要获取一个变量,get()
更安全一些,比如get(bar.name)[rab]
。但是您仍然 运行 陷入环境问题。由于您在 dopar
的正文中没有变量 bar
或 rab
,因此它们不会导出到 foreach
为 运行 的环境中代码。您可以通过显式分配 foreach 的 .export
参数来修复该问题,以确保导出这些变量。在这里我改为使用 get
并且只需要显式导出 bar
因为 rab
现在包含在函数的框中。
foo<-foreach(m = 1:10, .export=c("bar"), .packages = c("stats")) %dopar% {
get(bar.name)[rab]
}
一个更好的主意是指定一个命名列表的元素,而不是指定一个变量名。例如
baz <- list(bar=letters[1:4], bob=letters[5:7])
那你可以
baz.name <- "bar"
rab <- c(2,4)
foo<-foreach(m = 1:10, .packages = c("stats")) %dopar% {
baz[[baz.name]][rab]
}
并且因为 dopar 可以看到变量 baz
、baz.name
和 rab
,所以您无需导出任何内容。
我正在尝试将 foreach 与并行后端一起使用以加快计算速度(对 {AUCRF} 随机森林进行特征选择的交叉验证,如果这很重要的话)。在这样做的过程中,我需要获得向量的一个子集。向量的名称可以更改,但可以作为字符向量访问。我使用 eval(parse()) 构造(好主意?)来获取向量的一个子集。
示例:
library(parallel)
library(foreach)
library(stats)
#create cluster
clu <- makeCluster(detectCores() - 1)
registerDoParallel(clu, cores = detectCores() - 1)
bar<-c("a","b","c","d")
rab<-c(2,3)
bar.name<-"bar"
#expected output in this example is a list containing ten times
bar[rab]
#or
eval(parse(text=paste(bar.name,"[rab]",sep="")))
foo<-foreach(m = 1:10, .packages = c("stats")) %dopar% {
sink("foreach.txt")
print(bar.name)
print(parse(text=paste(bar.name,"[rab]",sep="")))
print(eval(parse(text=paste(bar.name,"[rab]",sep=""))))
foo.temp<-eval(parse(text=paste(bar.name,"[rab]",sep="")))
return(foo.temp)
}
sink()
stopCluster(clu)
但是我收到以下错误:
Error in { : task 1 failed - "Object 'bar' not found"
我认为每个工作人员都得到一份包含所有对象的工作区副本。知道我做错了什么吗?
这听起来像是一个糟糕的设计。几乎没有必要使用 eval(parse())
.
要获取一个变量,get()
更安全一些,比如get(bar.name)[rab]
。但是您仍然 运行 陷入环境问题。由于您在 dopar
的正文中没有变量 bar
或 rab
,因此它们不会导出到 foreach
为 运行 的环境中代码。您可以通过显式分配 foreach 的 .export
参数来修复该问题,以确保导出这些变量。在这里我改为使用 get
并且只需要显式导出 bar
因为 rab
现在包含在函数的框中。
foo<-foreach(m = 1:10, .export=c("bar"), .packages = c("stats")) %dopar% {
get(bar.name)[rab]
}
一个更好的主意是指定一个命名列表的元素,而不是指定一个变量名。例如
baz <- list(bar=letters[1:4], bob=letters[5:7])
那你可以
baz.name <- "bar"
rab <- c(2,4)
foo<-foreach(m = 1:10, .packages = c("stats")) %dopar% {
baz[[baz.name]][rab]
}
并且因为 dopar 可以看到变量 baz
、baz.name
和 rab
,所以您无需导出任何内容。