Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
并行plyr中的奇异环境行为_R_Parallel Processing_Plyr - Fatal编程技术网

并行plyr中的奇异环境行为

并行plyr中的奇异环境行为,r,parallel-processing,plyr,R,Parallel Processing,Plyr,最近,我在我的工作区中创建了一个对象factor=1,不知道base包中有一个函数factor 我打算在并行循环中使用变量factor,例如 library(plyr) library(foreach) library(doParallel) workers <- makeCluster(2) registerDoParallel(workers,cores=2) factor=1 llply( as.list(1:2), function(x) factor*x, .p

最近,我在我的工作区中创建了一个对象
factor=1
,不知道
base
包中有一个函数
factor

我打算在并行循环中使用变量
factor
,例如

library(plyr)
library(foreach)
library(doParallel)

workers <- makeCluster(2)
registerDoParallel(workers,cores=2)

factor=1

llply(
  as.list(1:2),
  function(x) factor*x,
  .parallel = TRUE,
  .paropts=list(.export=c("factor"))
     )
如果我们检查
llply
的输出,我们会看到
base::factor
中的行
factor\u=get(“factor”,envir=export\u env)
不返回
1
(对应于用户提供的对象),而是返回
base::factor
的函数定义

问题1)我如何理解这种行为?我希望输出是
1

问题2)如果我给另一个包中已经定义的对象分配了一个新值(例如在我的情况下,
factor
),是否有办法从
R
获得警告?

llply函数调用引擎盖下的“foreach”。Foreach使用“parant.frame()”确定要评估的环境。在llply的案例中,parant.frame是什么?它是llply的函数环境,没有定义因子

与其使用llply,为什么不直接使用foreach呢

library(plyr)
library(foreach)
library(doParallel)

workers <- makeCluster(2)
registerDoParallel(workers,cores=2)

factor=1
foreach(x=1:2) %dopar% {factor*x}
库(plyr)
图书馆(foreach)
图书馆(双平行)

工人首先,我应该注意,如果使用另一个未在
base
中使用的变量名,则错误会消失——例如,如果我们使用
a
而不是
factor
。这清楚地表明
llply
沿着其搜索路径在
factor
(值为1的变量)之前查找
base::factor
(函数)。我试图用简化版的
llply
复制此问题,即

library(plyr)
library(foreach)
library(doParallel)

workers <- makeCluster(2)
registerDoParallel(workers,cores=2)

factor=1

llply_simple=function(.x,.fun,.paropts) {
  #give current environment a name
  tmpEnv=environment()
  attr(tmpEnv,"name")="llply_simple_body"
  #print all enclosing envirs of llply_simple_body (see def of allEnv below)
  print(allEnv(tmpEnv))
  cat("------\nResults:\n")
  do.ply=function(i) {
    .fun(i)
  }
  fe_call <- as.call(c(list(quote(foreach::foreach), i = .x), .paropts))
  fe <- eval(fe_call)
  foreach::`%dopar%`(fe, do.ply(i))
}
有趣的是,简化的函数实际上按预期工作(即,给出
1
2
作为结果)

因此,
llply_simple
与完整的
plyr::llply
函数的唯一显著区别在于后者属于一个包。让我们尝试将
llply_simple
移动到一个包中

package.skeleton(list=c("llply_simple","allEnv"),name="llplyTest")
unlink("./llplyTest/DESCRIPTION")
devtools::create_description("./llplyTest",
                             extra=list("devtools.desc.author"='"T <t@t.com>"'))
tmp=readLines("./llplyTest/man/llply_simple.Rd")
tmp[which(grepl("\\\\title",tmp))+1]="Test1"
writeLines(tmp,"./llplyTest/man/llply_simple.Rd")
tmp=readLines("./llplyTest/man/allEnv.Rd")
tmp[which(grepl("\\\\title",tmp))+1]="Test2"
writeLines(tmp,"./llplyTest/man/allEnv.Rd")
devtools::install("./llplyTest")
突然之间,我们得到了与我2013年的原始问题相同的错误。因此,问题显然与从包中调用函数有关。让我们看看
allEnv
的输出:它基本上为我们提供了
llpy_simple
llplyTest::llpy_simple
用于查找应该导出的变量的环境序列。实际上是
foreach
进行导出,如果您有兴趣了解为什么
foreach
真正从我们命名为
llply\u simple\u body
的环境开始,请查看
foreach::%dopar%
的源代码,
foreach:::getDoPar
foreach:::.foreachGlobals$fun
并遵循
envir
参数的路径


我们现在可以清楚地看到,非包版本的搜索顺序与
llplyTest::llpy_simple
不同,包版本将首先在
base
中找到
因子

谢谢你的意见。这里的问题不在于评估环境,而在于
foreach
使用什么环境来查找应该导出的变量。如果使用的变量名未在
base
中使用,那么问题就会消失,比如说
a
而不是
factor
。我知道我可以直接使用
foreach
(就像你和我现在做的那样),然后错误就消失了。但回到2013年,我是一个重度
plyr
用户,这个错误让我非常困惑。所以,出于好奇,我想解决这个问题。
allEnv=function(x) {
  if (environmentName(x)=="R_EmptyEnv") {
    return(environmentName(x))
  } else {
    c(environmentName(x),allEnv(parent.env(x)))
  }
}
llply_simple(1:2,function(x) x*factor,list(.export="factor"))
#[1] "llply_simple_body"  "R_GlobalEnv"        "package:doParallel" "package:parallel"  
#[5] "package:iterators"  "package:foreach"    "package:plyr"       "tools:rstudio"     
#[9] "package:stats"      "package:graphics"   "package:grDevices"  "package:utils"     
#[13] "package:datasets"   "package:methods"    "Autoloads"          "base"              
#[17] "R_EmptyEnv"
#--------
#Results:        
#[[1]]
#[1] 1
#
#[[2]]
#[1] 2
package.skeleton(list=c("llply_simple","allEnv"),name="llplyTest")
unlink("./llplyTest/DESCRIPTION")
devtools::create_description("./llplyTest",
                             extra=list("devtools.desc.author"='"T <t@t.com>"'))
tmp=readLines("./llplyTest/man/llply_simple.Rd")
tmp[which(grepl("\\\\title",tmp))+1]="Test1"
writeLines(tmp,"./llplyTest/man/llply_simple.Rd")
tmp=readLines("./llplyTest/man/allEnv.Rd")
tmp[which(grepl("\\\\title",tmp))+1]="Test2"
writeLines(tmp,"./llplyTest/man/allEnv.Rd")
devtools::install("./llplyTest")
library(llplyTest)
llplyTest::llply_simple(1:2,function(x) x*factor,list(.export="factor"))
#[1] "llply_simple_body"  "llplyTest"          "imports:llplyTest"  "base"              
#[5] "R_GlobalEnv"        "package:doParallel" "package:parallel"   "package:iterators" 
#[9] "package:foreach"    "package:plyr"       "tools:rstudio"      "package:stats"     
#[13] "package:graphics"   "package:grDevices"  "package:utils"      "package:datasets"  
#[17] "package:methods"    "Autoloads"          "base"               "R_EmptyEnv"
#------
#Results:
#Error in do.ply(i) : 
#  task 1 failed - "non-numeric argument to binary operator"