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)
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="*"))))
TL; DR: benutze paste
.
create_ctree <- function(col){
myFormula <- paste(col, "~.", collapse="")
ctree(myFormula, data)
}
create_ctree("class")