web-dev-qa-db-fra.com

Formule avec nombre dynamique de variables

Supposons qu'il y ait des données.frame foo_data_frame et que l'on veuille trouver la régression de la colonne cible Y par d'autres colonnes. À cette fin, une formule et un modèle sont généralement utilisés. Par exemple:

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

Cela fonctionne bien si la formule est codée statiquement. Si l'on souhaite rooter plusieurs modèles avec le nombre constant de variables dépendantes (disons, 2), il peut être traité comme ça:

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

Ma question est de savoir comment faire le même effet lorsque le nombre de variables change dynamiquement pendant l'exécution du programme?

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?)
   }
}
67
Max

Voir ?as.formula, par exemple.:

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

factors est un vecteur de caractères contenant les noms des facteurs que vous souhaitez utiliser dans le modèle. Vous pouvez le coller dans un modèle lm, par exemple:

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
86
Joris Meys

Une fonction souvent oubliée est reformulate. De ?reformulate:

reformulate crée une formule à partir d'un vecteur de caractères.


Un exemple simple:

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

donnera cette formule:

y ~ factor1 + factor2


Bien que cela ne soit pas explicitement documenté, vous pouvez également ajouter des termes d'interaction:

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

donnera:

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

53
mnel

Une autre option pourrait être d'utiliser une matrice dans la formule:

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

lm(Y ~ foo[,factors])
10
Sacha Epskamp

Vous n'avez pas vraiment besoin d'une formule. Cela marche:

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

comme cela:

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

Je résous généralement ce problème en modifiant le nom de ma colonne de réponse. C'est plus facile à faire de manière dynamique, et peut-être plus propre.

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