Zuerst sollte ich beachten, dass der Fehler verschwindet, wenn man einen anderen Variablennamen verwendet, der nicht in base
verwendet wird - zum Beispiel, wenn wir a
anstelle von factor
verwenden. Dies zeigt deutlich, dass llply
base::factor
(eine Funktion) vor factor
(Variable mit Wert 1) entlang seines Suchpfades findet. Ich habe versucht, dieses Problem mit einer vereinfachten Version von llply
zu replizieren, das heißt,
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))
}
llply_simple
verwendet eine rekursive Hilfsfunktion (allEnv
), die durch alle einschließenden Umgebungen Schleifen. Es gibt einen Vektor mit allen Umwelt Namen
allEnv=function(x) {
if (environmentName(x)=="R_EmptyEnv") {
return(environmentName(x))
} else {
c(environmentName(x),allEnv(parent.env(x)))
}
}
Es ist interessant, dass die vereinfachte Funktion tatsächlich wie erwartet funktioniert (dh gibt 1
und 2
als Ergebnisse)
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
So ist der einzige signifikante Unterschied von llply_simple
mit Bezug auf die volle plyr::llply
Funktion ist, dass letztere zu einem Paket gehört. Lassen Sie uns versuchen, llply_simple
in ein Paket zu verschieben.
package.skeleton(list=c("llply_simple","allEnv"),name="llplyTest")
unlink("./llplyTest/DESCRIPTION")
devtools::create_description("./llplyTest",
extra=list("devtools.desc.author"='"T <[email protected]>"'))
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")
Und nun versuchen llplyTest::llply_simple
aus unserem neuen Paket 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"
Alle von uns den gleichen Fehler von 2013, wie in meiner ursprünglichen Frage kommen plötzlich auszuführen, so die Frage ist eindeutig mit Aufruf die Funktion aus einem Paket. Lassen Sie uns einen Blick auf die Ausgabe von allEnv
werfen: Es gibt uns im Grunde die Reihenfolge der Umgebungen, die llpy_simple
und llplyTest::llpy_simple
verwenden, um nach Variablen zu suchen, die exportiert werden sollen. Eigentlich ist es foreach
, dass der ausführende tut und wenn man daran interessiert zu sehen, warum foreach
wirklich mit der Umwelt beginnt, die wir llply_simple_body
genannt, Blick auf den Quellcode von foreach::%dopar%
, foreach:::getDoPar
und foreach:::.foreachGlobals$fun
und folgen Sie dem Pfad des envir
Argument.
Wir können nun deutlich sehen, dass die Nicht-Paketversion eine andere Suchsequenz als llplyTest::llpy_simple
hat und dass die Paketversion factor
zuerst in base
finden wird!
Vielen Dank für Ihre Eingabe. Das Problem hier ist nicht so sehr das Umfeld der Bewertung, sondern die Umgebung, in der foreach die Variablen findet, die exportiert werden sollen. Das Problem verschwindet, wenn man einen Variablennamen verwendet, der nicht in "base" verwendet wird, sagen wir "a" statt "faktor". Ich weiß, dass ich 'foreach' direkt verwenden kann (wie du es heute meistens tust) und dass der Fehler dann verschwindet. Aber im Jahr 2013 war ich ein schwerer "plyr" -Benutzer und dieser Fehler verwirrte mich ziemlich. Also wollte ich das aus Neugier lösen. – cryo111