Формула с динамическим числом переменных
Предположим, что есть некоторые data.frame foo_data_frame, и кто-то хочет найти регрессию целевого столбца Y некоторыми другими столбцами. Для этой цели обычно используются некоторые формулы и модели. Например:
linear_model <- lm(Y ~ FACTOR_NAME_1 + FACTOR_NAME_2, foo_data_frame)
Это хорошо работает, если формула закодирована статически. Если необходимо прогнать несколько моделей с постоянным числом зависимых переменных (скажем, 2), то можно обращаться так:
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...
}
}
Мой вопрос в том, как сделать то же самое, когда число переменных меняется динамически во время работы программы?
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
См. ?as.formula
, например:
factors <- c("factor1", "factor2")
as.formula(paste("y~", paste(factors, collapse="+")))
# y ~ factor1 + factor2
где factors
- вектор символов, содержащий имена факторов, которые вы хотите использовать в модели. Это можно вставить в модель lm
, например:
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
Ответ 2
Часто забытая функция reformulate
. От ?reformulate
:
reformulate
создает формулу из символьного вектора.
Простой пример:
listoffactors <- c("factor1","factor2")
reformulate(termlabels = listoffactors, response = 'y')
даст следующую формулу:
y ~ factor1 + factor2
Хотя это явно не документировано, вы также можете добавить условия взаимодействия:
listofintfactors <- c("(factor3","factor4)^2")
reformulate(termlabels = c(listoffactors, listofintfactors),
response = 'y')
даст:
y ~ factor1 + factor2 + (factor3 + factor4)^2
Ответ 3
Другим вариантом может быть использование матрицы в формуле:
Y = rnorm(10)
foo = matrix(rnorm(100),10,10)
factors=c(1,5,8)
lm(Y ~ foo[,factors])
Ответ 4
Вам действительно не нужна формула. Это работает:
lm(data_frame[c("Y", "factor1", "factor2")])
как это делает:
v <- c("Y", "factor1", "factor2")
do.call("lm", list(bquote(data_frame[.(v)])))
Ответ 5
Обычно я решаю это, изменяя имя столбца ответа. Это проще сделать динамически и, возможно, более чистым.
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, ...)