2011-02-09 15 views
55

Przypuśćmy, że istnieje jakiś data.frame foo_data_frame i chce się dowiedzieć regresji kolumny docelowej Y niektórych innych kolumn. W tym celu zwykle stosuje się pewną formułę i model. Na przykład:Formula z numerem dynamicznego zmiennych

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

To działa dobrze, jeśli formuła jest kodowana statycznie. Jeśli pożądane jest korzeń ciągu kilku modeli ze stałą liczbą zmiennych zależnych (powiedzmy, 2) nie mogą być traktowane tak:

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... 
    } 
} 

Moje pytanie brzmi, jak zrobić taki sam wpływ, gdy liczba zmiennych jest zmieniając się dynamicznie podczas pracy programu?

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?) 
    } 
} 
+1

Dzięki!Twój środkowy przykład uświadomił mi, że nie potrzebuję rozwiązania twojego pytania i mogę zrobić coś znacznie prostszego! –

Odpowiedz

65

Zobacz ?as.formula, np .:

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

gdzie factors jest wektorem znaków zawierających nazwy czynników, których chcesz używać w modelu. To można wkleić do modelu lm, np .:

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 
+0

wielkie dzięki! R ma wiele użytecznych metod asany i jest super :) – Max

10

Innym rozwiązaniem mogłoby być wykorzystanie matrycy w formule:

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

lm(Y ~ foo[,factors]) 
+3

+1, ale należy pamiętać, że nie pozwala to na korzystanie z efektów interakcji. W tym celu można również zbudować matrycę modelu (patrz '? Model.matrix') –

3

rzeczywistości nie potrzebują formułę. To działa:

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

jak to robi:

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

+1 Bardzo poprawne, ale znowu trzeba będzie użyć modelu.matrix do skonstruowania macierzy z efektami interakcji. –

42

Funkcja często zapomina się reformulate. Od ?reformulate:

reformulate tworzy formułę z wektora znaków.


Prosty przykład:

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

przyniesie wzoru:

y ~ factor1 + factor2


chociaż nie są wyraźnie udokumentowane, można również dodać warunki interakcji:

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

przyniesie:

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

+2

@JorisMeys A to o wiele przyjemniejsze, ponieważ pozwala dodawać terminy interakcji! Od lat szukam podobnego rozwiązania ... – landroni

0

ja generalnie rozwiązać ten problem poprzez zmianę nazwy mojego kolumnie reakcji. Łatwiej jest robić to dynamicznie i być może czystsze.

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, ...)