Formel mit dynamischer Anzahl von Variablen


82

Angenommen, es gibt einige data.frame foo_data_frame und man möchte die Regression der Zielspalte Y durch einige andere Spalten finden. Zu diesem Zweck werden üblicherweise einige Formeln und Modelle verwendet. Zum Beispiel:

linear_model <- lm(Y ~ FACTOR_NAME_1 + FACTOR_NAME_2, foo_data_frame)

Das funktioniert gut, wenn die Formel statisch codiert ist. Wenn mehrere Modelle mit der konstanten Anzahl abhängiger Variablen (z. B. 2) verwurzelt werden sollen, kann dies folgendermaßen behandelt werden:

for (i in seq_len(factor_number)) {
  for (j in seq(i + 1, factor_number)) {
    linear_model <- lm(Y ~ F1 + F2, list(Y=foo_data_frame$Y,
                                         F1=foo_data_frame[[i]],
                                         F2=foo_data_frame[[j]]))
    # linear_model further analyzing...
  }
}

Meine Frage ist, wie man den gleichen Effekt macht, wenn sich die Anzahl der Variablen während der Programmausführung dynamisch ändert.

for (number_of_factors in seq_len(5)) {
   # Then root over subsets with #number_of_factors cardinality.
   for (factors_subset in all_subsets_with_fixed_cardinality) {
     # Here I want to fit model with factors from factors_subset.
     linear_model <- lm(Does R provide smth to write here?)
   }
}

2
Vielen Dank! Ihr mittleres Beispiel hat mir klar gemacht, dass ich die Lösung für Ihre Frage nicht brauchte und etwas viel Einfacheres tun könnte!
Mark Adamson

Antworten:


103

Siehe ?as.formulazB:

factors <- c("factor1", "factor2")
as.formula(paste("y~", paste(factors, collapse="+")))
# y ~ factor1 + factor2

Dabei factorshandelt es sich um einen Zeichenvektor, der die Namen der Faktoren enthält, die Sie im Modell verwenden möchten. Dies können Sie in ein lmModell einfügen , z.

set.seed(0)
y <- rnorm(100)
factor1 <- rep(1:2, each=50)
factor2 <- rep(3:4, 50)
lm(as.formula(paste("y~", paste(factors, collapse="+"))))

# Call:
# lm(formula = as.formula(paste("y~", paste(factors, collapse = "+"))))

# Coefficients:
# (Intercept)      factor1      factor2  
#    0.542471    -0.002525    -0.147433

66

Eine oft vergessene Funktion ist reformulate. Von ?reformulate:

reformulate Erstellt eine Formel aus einem Zeichenvektor.


Ein einfaches Beispiel:

listoffactors <- c("factor1","factor2")
reformulate(termlabels = listoffactors, response = 'y')

ergibt diese Formel:

y ~ factor1 + factor2


Obwohl nicht explizit dokumentiert, können Sie auch Interaktionsbegriffe hinzufügen:

listofintfactors <- c("(factor3","factor4)^2")
reformulate(termlabels = c(listoffactors, listofintfactors), 
    response = 'y')

wird ergeben:

y ~ factor1 + factor2 + (factor3 + factor4)^2


3
@JorisMeys Und es ist so viel schöner, als es das Hinzufügen von Interaktionsbegriffen ermöglicht! Ich habe jahrelang nach einer ähnlichen Lösung gesucht ..
landroni

Was ist, wenn die x-Variablen Leerzeichen enthalten? Sagen Sie "Faktor 1", "Faktor 2" usw.
Axiom

11

Eine andere Möglichkeit könnte darin bestehen, eine Matrix in der Formel zu verwenden:

Y = rnorm(10)
foo = matrix(rnorm(100),10,10)
factors=c(1,5,8)

lm(Y ~ foo[,factors])

3
+1, aber beachten Sie, dass dies keine Interaktionseffekte zulässt. Dafür kann man auch eine Modellmatrix konstruieren (siehe ?model.matrix)
Joris Meys

4

Sie brauchen eigentlich keine Formel. Das funktioniert:

lm(data_frame[c("Y", "factor1", "factor2")])

wie das:

v <- c("Y", "factor1", "factor2")
do.call("lm", list(bquote(data_frame[.(v)])))

+1 Sehr korrekt, aber auch hier müssten Sie model.matrix verwenden, um eine Matrix mit Interaktionseffekten zu erstellen.
Joris Meys

0

Ich löse dieses Problem im Allgemeinen, indem ich den Namen meiner Antwortspalte ändere. Es ist einfacher, dynamisch und möglicherweise sauberer zu arbeiten.

model_response <- "response_field_name"
setnames(model_data_train, c(model_response), "response") #if using data.table
model_gbm <- gbm(response ~ ., data=model_data_train, ...)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.