2015-09-16 7 views
12

Ich versuche eine sparsamere Version der this Lösung zu erstellen, die die Angabe der RHS einer Formel in der Form d1 + d1:d2 beinhaltet.Definition eines Infix-Operators zur Verwendung in einer Formel

Da * in Zusammenhang mit einer Formel ist ein prägnanter Stand-in für die vollständige Interaktion (dh d1 * d2 gibt d1 + d2 + d1:d2), hat mein Ansatz gewesen, einen alternativen Betreiber zu versuchen und zu definieren, sagen %+:% den Infix-Ansatz Ich habe in anderen Anwendungen gewohnt gewachsen, a la:

"%+:%" <- function(d1,d2) d1 + d2 + d1:d2 

dies ist jedoch nicht vorhersagbar, weil ich über Auswertung nicht vorsichtig gewesen; Lassen Sie uns ein Beispiel vorstellen zu meinen Fortschritt veranschaulichen:

set.seed(1029) 
v1 <- runif(1000) 
v2 <- runif(1000) 
y <- .8*(v1 < .3) + .2 * (v2 > .25 & v2 < .8) - 
    .4 * (v2 > .8) + .1 * (v1 > .3 & v2 > .8) 

Mit diesem Beispiel, es ist hoffentlich klar, warum nur die beiden Begriffe auszuschreiben könnte unerwünscht sein:

y ~ cut(v2, breaks = c(0, .25, .8, 1)) + 
    cut(v2, breaks = c(0, .25, .8, 1)):I(v1 < .3) 

Eine Abhilfe, die auf meine gewünschte Ausgabe Nähe ist die gesamte Formel als eine Funktion zu definieren:

plus.times <- function(outvar, d1, d2){ 
    as.formula(paste0(quote(outvar), "~", quote(d1), 
        "+", quote(d1), ":", quote(d2))) 
} 

dies das erwartete Koeffizienten gibt, wenn zu lm, aber mit den Namen übergeben, die ein re schwieriger zu interpretieren direkt (vor allem in den realen Daten, wo wir kümmern d1 und d2 Namen, im Gegensatz zu diesem allgemeinen Beispiel geben):

out1 <- lm(y ~ cut(v2, breaks = c(0, .25, .8, 1)) + 
      cut(v2, breaks = c(0, .25, .8, 1)):I(v1 < .3)) 
out2 <- lm(plus.times(y, cut(v2, breaks = c(0, .25, .8, 1)), I(v1 < .3))) 
any(out1$coefficients != out2$coefficients) 
# [1] FALSE 
names(out2$coefficients) 
# [1] "(Intercept)"   "d1(0.25,0.8]"  "d1(0.8,1]"   "d1(0,0.25]:d2TRUE" 
# [5] "d1(0.25,0.8]:d2TRUE" "d1(0.8,1]:d2TRUE" 

Also das weniger als optimal ist.

Gibt es eine Möglichkeit, den Code so anzupassen, dass der oben erwähnte Infix-Operator wie erwartet funktioniert? Wie wäre es, die Form von plus.times so zu ändern, dass die Variablen nicht umbenannt werden?

Ich habe Stochern (?formula, ?"~", ?":", getAnywhere(formula.default), this Antwort, etc.), aber noch nicht gesehen, wie genau R * interpretiert, wenn es in einer Formel begegnet ist, so dass ich meine gewünschten kleineren Anpassungen vornehmen kann .

+0

sie in Statistiken ::: model.frame.default in c interpretiert https://github.com/wch/r-source/blob/ed66b715221d2720f5b334470335635bada520b1/src/library/stats/src/model.c#L888 – rawr

+0

@rawr danke. Ich kann nicht sagen, dass ich eine Ahnung davon habe, was im C-Code vor sich geht - ich sehe, dass sie jedes der Symbole definieren, die von 'formula' verstanden werden, aber sie scheinen nur' tildeSymbol' zu verwenden. Bedeutet das überhaupt, dass ich nicht in der Lage sein werde, mein eigenes Infix zu bekommen, ohne zu C & defining zu gehen, sagen wir "plusColonSymbol" wie hier? – MichaelChirico

+1

@ HeatherTurner Antwort scheint genau richtig zu mir. Wenn Sie wirklich anfangen wollen, sich mit expandierenden Formeln zu messen, würde ich vorschlagen, mit (1) die 'terms' Komponente der Ergebnisse von' model.frame() 'zu betrachten und (2) den Code [hier] zu betrachten (https : //github.com/glmmTMB/glmmTMB/blob/master/glmmTMB/R/utils.R) ... –

Antwort

6

Sie müssen in diesem Fall keinen neuen Operator definieren: In einer Formel wird d1/d2 auf d1 + d1:d2 erweitert. Mit anderen Worten, d1/d2 gibt an, dass d2 innerhalb von d1 verschachtelt ist. & Weiter Beispiel:

out3 <- lm(y ~ cut(v2,breaks=c(0,.25,.8,1))/I(v1 < .3)) 
all.equal(coef(out1), coef(out3)) 
# [1] TRUE 

Weitere Kommentare

Faktoren sein können oder verschachtelte gekreuzt. Zwei Faktoren werden überschritten, wenn es möglich ist, jede Kombination von Ebenen der zwei Faktoren zu beobachten, z. Geschlecht und Behandlung, Temperatur und pH-Wert usw. Ein Faktor ist innerhalb eines anderen verschachtelt, wenn jedes Niveau dieses Faktors nur innerhalb eines der Niveaus des anderen Faktors beobachtet werden kann, z.B. Stadt und Land, Mitarbeiter und Filiale usw.

Diese Beziehungen spiegeln sich in der Parametrisierung des Modells wider.Für gekreuzte Faktoren verwenden wir d1*d2 oder d1 + d2 + d1:d2, um den Haupteffekt jedes Faktors plus die Wechselwirkung zu geben. Bei verschachtelten Faktoren verwenden wir d1/d2 oder d1 + d1:d2 eine separate submodel der Form 1 + d2 für jede Ebene der d1 zu geben.

Die Idee der Verschachtelung ist nicht auf Faktoren beschränkt, zum Beispiel können wir sex/x verwenden, um eine separate lineare Regression auf x für Männer und Frauen zu passen.

In einer Formel entspricht %in%:, aber es kann verwendet werden, um die verschachtelte oder hierarchische Struktur des Datenmodells hervorzuheben. Zum Beispiel ist a + b %in% a das gleiche wie , aber das Lesen von "a plus b in a" gibt eine bessere Beschreibung des Modells, das eingebaut wird. Dennoch hat die Verwendung von / den Vorteil, die Modellformel gleichzeitig zu vereinfachen und die Struktur hervorzuheben.