Seltsames Umgebungsverhalten in Parallel-Plr

8

Vor kurzem habe ich ein Objekt factor=1 in meinem Arbeitsbereich erstellt, ohne zu wissen, dass im Paket factor eine Funktion base vorhanden ist.

Was ich tun wollte, war, die Variable factor innerhalb einer parallelen Schleife zu verwenden, z. B.

%Vor%

Dies führt jedoch zu einem Fehler, der mich so lange brauchte, um es zu verstehen. Wie es scheint, erstellt plyr das Objekt factor in seiner Umgebung exportEnv , aber verwendet base::factor anstelle des vom Benutzer bereitgestellten Objekts. Siehe das folgende Beispiel

%Vor%

Wenn wir die Ausgabe von llply inspizieren, sehen wir, dass die Zeile factor_in_exportenv=get("factor",envir=export_env) nicht 1 zurückgibt (entspricht dem vom Benutzer bereitgestellten Objekt), sondern die Funktionsdefinition von base::factor .

Frage 1) Wie kann ich dieses Verhalten verstehen? Ich hätte erwartet, dass die Ausgabe 1 wäre.

Frage 2) Gibt es eine Möglichkeit, eine Warnung von R zu erhalten, wenn ich einem Objekt, das bereits in einem anderen Paket definiert war (z. B. factor ), einen neuen Wert zuweise?

    
cryo111 24.07.2013, 16:48
quelle

2 Antworten

0

Zunächst sollte ich bemerken, 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 Suchpfads findet. Ich habe versucht, dieses Problem mit einer vereinfachten Version von llply zu replizieren, d. H.

%Vor%

llply_simple verwendet eine rekursive Hilfsfunktion ( allEnv ), die alle umschließenden Umgebungen durchläuft. Es gibt einen Vektor mit allen Umgebungsnamen zurück

%Vor%

Es ist interessant, dass die vereinfachte Funktion tatsächlich wie erwartet funktioniert (d. h. 1 und 2 als Ergebnisse liefert)

%Vor%

Also ist der einzige signifikante Unterschied von llply_simple in Bezug auf die vollständige plyr::llply -Funktion, dass letztere zu einem Paket gehört. Versuchen wir, llply_simple in ein Paket zu verschieben.

%Vor%

Und nun versuchen Sie llplyTest::llply_simple von unserem neuen Paket llplyTest

auszuführen %Vor%

Plötzlich erhalten wir den gleichen Fehler wie in meiner ursprünglichen Frage von 2013. Das Problem ist also eindeutig mit dem Aufruf der Funktion aus einem Paket verbunden. Sehen wir uns die Ausgabe von allEnv an: Sie gibt uns im Grunde die Abfolge der Umgebungen an, die llpy_simple und llplyTest::llpy_simple verwenden, um nach Variablen zu suchen, die exportiert werden sollen. Eigentlich ist es foreach , das den Export macht und wenn man interessiert, warum foreach wirklich mit der Umgebung beginnt, die wir llply_simple_body genannt haben, schaut euch den Quellcode von foreach::%dopar% , foreach:::getDoPar und foreach:::.foreachGlobals$fun an Folge dem Pfad des envir -Arguments.

Wir können jetzt klar erkennen, dass die Nicht-Paket-Version eine andere Suchsequenz als llplyTest::llpy_simple hat und dass die Paket-Version factor in base zuerst findet!

    
cryo111 10.12.2016, 17:02
quelle
1

Die Funktion llply ruft "foreach" unter der Haube auf. Foreach verwendet "parant.frame ()", um die zu bewertende Umgebung zu bestimmen. Was ist der parant.frame im Fall von lplly? Es ist die Funktionsumgebung der llply, für die kein Faktor definiert ist.

Warum sollte fleach nicht direkt verwendet werden, anstatt llply zu verwenden?

%Vor%

Beachten Sie, dass Sie den Parameter .export nicht einmal benötigen, da dies in diesem Fall automatisch der Fall ist.

    
thc 09.12.2016 03:35
quelle

Tags und Links