Ich muss ein Regressionsmodell innerhalb einer Funktion aktualisieren. Idealerweise sollte die Funktion mit jeder Art von Modellen funktionieren ( lm
, glm
, multinom
, clm
). Genauer gesagt, muss ich eine oder mehrere Kovariaten hinzufügen, die innerhalb der Funktion definiert sind. Hier ist ein Beispiel.
Hier ist ein Beispiel für die Verwendung
%Vor%Fehler in eval (expr, envir, enclos): Objekt 'randData' nicht gefunden
Hier ist ein weiteres Beispiel mit glm
%Vor%Irgendeine Idee?
Das Problem ist, dass var1
im Datenrahmen und in der Umgebung des Modells nachgeschlagen wird, aber nicht in der Umgebung in MyUpdate
.
1) Um dieses Problem zu vermeiden, aktualisieren Sie das Modell nicht nur mit der überarbeiteten Formel, sondern auch mit einem überarbeiteten Datenrahmen, der var1
enthält:
Das Obige ist wahrscheinlich die beste Lösung von denen, die in dieser Antwort vorgestellt werden, da es vermeidet, sich mit inneren Strukturen herumzuschlagen. Es scheint für lm
, glm
, multinom
und clm
zu funktionieren. Die anderen unten aufgeführten Lösungen sind mit internen Strukturen behaftet und daher weniger allgemein bei Modellanpassungsroutinen. Alle anderen arbeiten mit lm
, funktionieren aber möglicherweise nicht für andere.
test Hier ist ein Test, der ohne Fehler bei jeder der in der Frage erwähnten Modellanpassungsfunktionen abläuft, wenn MyUpdate
wie oben ist und auch die Lösungen in (2) die Tests ohne ausführen Error. Die Lösung (3) funktioniert mindestens mit lm
.
Die verbleibenden Lösungen haben einen direkteren Zugriff auf die Interna und machen sie weniger robust gegenüber Änderungen der Modellfunktion.
2) Verblüffen mit Umgebungen
Zusätzlich gibt es drei Lösungen, die mit Umgebungen zu tun haben. Der erste ist der sauberste, gefolgt von dem zweiten und dann dem dritten. Das dritte ist das am wenigsten akzeptable, da es tatsächlich var1
in die Umgebung des Modells schreibt (gefährlich var1
dort überschreiben), aber es ist das Kürzeste. Sie arbeiten mit lm
, glm
multinom
und clm
.
Beachten Sie, dass wir var1
nicht wirklich in einen Datenrahmen setzen müssen, noch muss die Aktualisierungsformel in Anführungszeichen gesetzt werden, und wir haben beide in allen folgenden Beispielen geändert. Auch die return
-Anweisung kann entfernt werden und wir haben das auch getan.
2a) Im Folgenden wird die Umgebung des ursprünglichen Modells so geändert, dass sie auf ein neues Proxy-Proto-Objekt verweist, das var1
enthält, dessen übergeordnetes Element die ursprüngliche Modellumgebung ist. Hier ist proto(p, var1 = rnorm(n))
das Proxy-Proto-Objekt (ein Proto-Objekt ist eine Umgebung mit unterschiedlicher Semantik) und p
ist das übergeordnete Element des Proxy.
Weitere Informationen finden Sie im Abschnitt "Proxies" in diesem Dokument: Ссылка
2b) Dies könnte alternativ auch ohne proto geschehen, aber auf Kosten der Erweiterung der ## Zeile auf drei Zeilen mit einigen zusätzlichen hässlichen Umgebungsmanipulationen. Hier ist e
die Proxy-Umgebung.
2c) Kürzester, aber am meisten hackish ist es, var1
in die ursprüngliche model
-Umgebung zu stecken:
3) eval / substitute Diese Lösung verwendet eval
, was manchmal verpönt ist. Es funktioniert bei lm
und glm
und bei clm
funktioniert es, außer dass die Ausgabe nicht var1
anzeigt, sondern den Ausdruck, der sie berechnet.
ÜBERARBEITET Zusätzliche Lösungen hinzugefügt, vereinfacht (1), hat Lösungen in (2) bekommen, um alle Beispiele im Testabschnitt auszuführen.
Eine Theorie . Ein Formelobjekt hat oft eine zugeordnete Umgebung:
%Vor% Hier wissen die Funktionen von frm1
, dass sie nach y
und x
in der globalen Umgebung suchen sollen (sofern nicht anders angegeben, siehe z. B. data
arg von lm()
). Auf der anderen Seite:
Eine solche Formel zeigt auf y
und x
als "lokale Variablen" in f()
.
Wenn Sie eine in der globalen Umgebung erstellte Formel an eine Funktion übergeben, können Sie in den meisten Fällen nicht auf die Objekte verweisen, die in dieser Funktion erstellt wurden.
Die Lösung . Die zugrundeliegende Formel und Umgebung ist mit dem von lm()
zurückgegebenen Objekt etwas "versteckt". Aber sie sind zugänglich. Der folgende Code sollte Ihr Problem lösen.