webentwicklung-frage-antwort-db.com.de

Wie werden Referenzvariablen nach Zeichenfolge in einer Formel verwendet?

Im folgenden minimalen Beispiel versuche ich, die Werte einer Zeichenfolge vars in einer Regressionsformel zu verwenden. Ich kann jedoch nur die Zeichenfolge der Variablennamen ("v2 + v3 + v4") an die Formel übergeben, nicht die tatsächliche Bedeutung dieser Zeichenfolge (z. B. "v2" ist dat $ v2).

Ich weiß, dass es bessere Möglichkeiten gibt, die Regression auszuführen (z. B. lm(v1 ~ v2 + v3 + v4, data=dat)). Meine Situation ist komplexer und ich versuche herauszufinden, wie man eine Zeichenkette in einer Formel verwendet. Irgendwelche Gedanken?

nter Code aktualisiert

# minimal example 
# create data frame
v1 <- rnorm(10)
v2 <- sample(c(0,1), 10, replace=TRUE)
v3 <- rnorm(10)
v4 <- rnorm(10)
dat <- cbind(v1, v2, v3, v4)
dat <- as.data.frame(dat)

# create objects of column names
c.2 <- colnames(dat)[2]
c.3 <- colnames(dat)[3]
c.4 <- colnames(dat)[4]

# shortcut to get to the type of object my full code produces
vars <- paste(c.2, c.3, c.4, sep="+")

### TRYING TO SOLVE FROM THIS POINT:
print(vars)
# [1] "v2+v3+v4"

# use vars in regression
regression <- paste0("v1", " ~ ", vars)
m1 <- lm(as.formula(regression), data=dat)

Update: @Arun hat im ersten Beispiel das "" Fehlen von v1 Korrigiert. Das hat mein Beispiel gefixt, aber ich hatte immer noch Probleme mit meinem echten Code. Im folgenden Codeabschnitt habe ich mein Beispiel angepasst, um meinen tatsächlichen Code besser widerzuspiegeln. Ich habe mich für ein einfacheres Beispiel entschieden, als ich zunächst dachte, das Problem sei die Zeichenfolge vars.

Hier ist ein Beispiel, das nicht funktioniert :) Verwendet denselben Datenrahmen dat, der oben erstellt wurde.

dv <- colnames(dat)[1]
r2 <- colnames(dat)[2]
# the following loop creates objects r3, r4, r5, and r6
# r5 and r6 are interaction terms
for (v in 3:4) {
  r <- colnames(dat)[v]
  assign(paste("r",v,sep=""),r)
  r <- paste(colnames(dat)[2], colnames(dat)[v], sep="*")
  assign(paste("r",v+2,sep=""),r)
}

# combine r3, r4, r5, and r6 then collapse and remove trailing +
vars2 <- sapply(3:6, function(i) { 
                paste0("r", i, "+")
                })
vars2 <- paste(vars2, collapse = '')
vars2 <- substr(vars2, 1, nchar(vars2)-1)

# concatenate dv, r2 (as a factor), and vars into `eq`
eq <- paste0(dv, " ~ factor(",r2,") +", vars2)

Hier ist das Problem:

print(eq)
# [1] "v1 ~ factor(v2) +r3+r4+r5+r6"

Im Gegensatz zu regression im ersten Beispiel werden bei eq die Spaltennamen nicht eingefügt (z. B. v3). Die Objektnamen (z. B. r3) Bleiben erhalten. Daher funktioniert der folgende Befehl lm() nicht.

m2 <- lm(as.formula(eq), data=dat)
40
Eric Green

Ich sehe hier ein paar Probleme. Erstens, und ich glaube nicht, dass dies irgendwelche Probleme verursacht, aber lassen Sie uns Ihren Datenrahmen in einem Schritt erstellen, damit Sie nicht v1 Bis v4 In der globalen Umgebung wie in beiden schweben auch im Datenrahmen. Zweitens wollen wir hier nur v2 Zu einem Faktor machen, damit wir uns später nicht damit befassen müssen, ihn zu einem Faktor zu machen.

dat <- data.frame(v1 = rnorm(10),
                  v2 = factor(sample(c(0,1), 10, replace=TRUE)),
                  v3 = rnorm(10),
                  v4 = rnorm(10) )

Teil Eins Nun, für Ihren ersten Teil sieht es so aus, als ob Sie folgendes möchten:

lm(v1 ~ v2 + v3 + v4, data=dat)

Hier ist eine einfachere Möglichkeit, dies zu tun, obwohl Sie die Antwortvariable noch angeben müssen.

lm(v1 ~ ., data=dat)

Alternativ können Sie die Funktion natürlich auch mit Einfügen aufbauen und lm aufrufen.

f <- paste(names(dat)[1], "~", paste(names(dat)[-1], collapse=" + "))
# "v1 ~ v2 + v3 + v4"
lm(f, data=dat)

In diesen Situationen bevorzuge ich jedoch die Verwendung von do.call, Die Ausdrücke auswertet, bevor sie an die Funktion übergeben werden. Dadurch eignet sich das resultierende Objekt besser zum Aufrufen von Funktionen wie update on. Vergleichen Sie den Teil call der Ausgabe.

do.call("lm", list(as.formula(f), data=as.name("dat")))

Teil Zwei In Bezug auf Ihren zweiten Teil sieht es so aus, als würden Sie folgendes anstreben:

lm(factor(v2) + v3 + v4 + v2*v3 + v2*v4, data=dat)

Erstens, weil v2 Ein Faktor im Datenrahmen ist, brauchen wir diesen Teil nicht, und zweitens kann dies weiter vereinfacht werden, indem die Methoden von R zur Verwendung von arithmetischen Operationen zur Erzeugung von Interaktionen wie dieser besser verwendet werden.

lm(v1 ~ v2*(v3 + v4), data=dat)

Ich würde die Funktion dann einfach mit paste erstellen. Die Schleife mit assign ist wahrscheinlich auch im größeren Fall keine gute Idee.

f <- paste(names(dat)[1], "~", names(dat)[2], "* (", 
           paste(names(dat)[-c(1:2)], collapse=" + "), ")")
# "v1 ~ v2 * ( v3 + v4 )"

Es kann dann entweder direkt mit lm oder mit do.call Aufgerufen werden.

lm(f, data=dat)
do.call("lm", list(as.formula(f), data=as.name("dat")))

Über Ihren Code Das Problem, das Sie beim Versuch hatten, r3 Usw. zu verwenden, war, dass Sie den Inhalt der Variablen r3 Und nicht den Wert r3 Haben wollten. . Um den Wert zu erhalten, benötigen Sie get, und dann würden Sie die Werte zusammen mit paste reduzieren.

vars <- sapply(paste0("r", 3:6), get)
paste(vars, collapse=" + ")

Ein besserer Weg wäre jedoch, assign zu vermeiden und einfach einen Vektor der von Ihnen gewünschten Begriffe zu erstellen.

vars <- NULL
for (v in 3:4) {
  vars <- c(vars, colnames(dat)[v], paste(colnames(dat)[2], 
                                          colnames(dat)[v], sep="*"))
}
paste(vars, collapse=" + ")

Eine R-ähnliche Lösung wäre die Verwendung von lapply:

vars <- unlist(lapply(colnames(dat)[3:4], 
                      function(x) c(x, paste(colnames(dat)[2], x, sep="*"))))
51
Aaron

TL; DR: benutze paste.

create_ctree <- function(col){
    myFormula <- paste(col, "~.", collapse="")
    ctree(myFormula, data)
}
create_ctree("class")
3
Travis Heeter