Объединение cbind и paste в линейной модели

Я хотел бы знать, как я могу придумать синтаксис формулы lm, который позволил бы мне использовать paste вместе с cbind для множественной многомерной регрессии.

Пример

В моей модели у меня есть набор переменных, который соответствует примитивному примеру ниже:

data(mtcars)
depVars <- paste("mpg", "disp")
indepVars <- paste("qsec", "wt", "drat")

Проблема

Я хотел бы создать модель с моими depVars и indepVars. Модель, набранная вручную, будет выглядеть так:

modExmple <- lm(formula = cbind(mpg, disp) ~ qsec + wt + drat, data = mtcars)

Я хочу сгенерировать ту же формулу, не обращаясь к именам переменных и используя только векторы depVars и indepVars, определенные выше.


Попытка 1

Например, то, что я имел в виду, будет соответствовать:

mod1 <- lm(formula = formula(paste(cbind(paste(depVars, collapse = ",")), " ~ ",
                                   indepVars)), data = mtcars)

Попытка 2

Я тоже пробовал это:

mod2 <- lm(formula = formula(cbind(depVars), paste(" ~ ",
                                                   paste(indepVars, 
                                                         collapse = " + "))),
           data = mtcars)

Дополнительные примечания

  • Я нашел несколько хороших примеров использования paste с формулой, но я хотел бы знать, как я могу сочетаться с cbind.
  • В основном это вопрос синтаксиса; в моих реальных данных у меня есть ряд переменных, которые я хотел бы ввести в модель, и использование ранее сгенерированного вектора более экономно и делает код более презентабельным. По сути, меня интересует только создание объекта формулы, который будет содержать cbind с именами переменных, соответствующими одному вектору, и остальными переменными, соответствующими другому вектору.
  • Одним словом, я хочу получить формулу в modExample без ввода имен переменных.

person Konrad    schedule 01.02.2016    source источник
comment
depVars — это string с пробелом. Вы можете использовать paste(c("qsec", "wt", "drat"), collapse='+')   -  person akrun    schedule 01.02.2016
comment
@akrun Спасибо за вклад, я предполагаю, что это должно быть что-то в этих строках, но синтаксис formula(cbind(paste(depVars)), " ~ ", paste(indepVars, collapse='+')), data = mtcars) не будет работать. Где я застреваю, так это в сочетании cbind / paste.   -  person Konrad    schedule 01.02.2016
comment
Может быть, поможет использование reformulate?   -  person Konrad    schedule 01.02.2016
comment
Похоже, reformulate может помочь. Я думаю проблема в paste(depVars))   -  person akrun    schedule 01.02.2016
comment
@akrun Да, я также вижу, что было бы лучше, если бы векторы с именами переменных определялись через c(), а не paste().   -  person Konrad    schedule 01.02.2016
comment
@akrun Наслаждайтесь чаем :) Я тоже могу его выпить. Кстати, это почти работает reformulate(paste("cbind(", paste(depVars, collapse = " , "), ") ~ ", paste(indepVars, collapse = " + ")))   -  person Konrad    schedule 01.02.2016


Ответы (2)


Думаю, это работает.

data(mtcars)
depVars <- c("mpg", "disp")
indepVars <- c("qsec", "wt", "drat")

lm(formula(paste('cbind(',
                 paste(depVars, collapse = ','),
                 ') ~ ',
                 paste(indepVars, collapse = '+'))), data = mtcars)
person danas.zuokas    schedule 01.02.2016
comment
Ха! Спасибо большое. Добирались потихоньку, у меня было предчувствие, что с cbind( что-то будет. Кстати, это интересный способ написания кода, вроде печально известного concatenate в Excel. Большое спасибо за ваш вклад! - person Konrad; 01.02.2016

Во всех приведенных ниже решениях используются эти определения:

depVars <- c("mpg", "disp")
indepVars <- c("qsec", "wt", "drat")

1) формула строки символов Создайте строку символов, представляющую формулу, а затем запустите lm с помощью do.call. Обратите внимание, что формула, показанная в выходных данных, отображается правильно и записывается.

fo <- sprintf("cbind(%s) ~ %s", toString(depVars), paste(indepVars, collapse = "+"))
do.call("lm", list(fo, quote(mtcars)))

давая:

Call:
lm(formula = "cbind(mpg, disp) ~ qsec+wt+drat", data = mtcars)

Coefficients:
             mpg       disp    
(Intercept)   11.3945  452.3407
qsec           0.9462  -20.3504
wt            -4.3978   89.9782
drat           1.6561  -41.1148

1a) Это также сработает:

fo <- sprintf("cbind(%s) ~.", toString(depVars))
do.call("lm", list(fo, quote(mtcars[c(depVars, indepVars)])))

давая:

Call:
lm(formula = cbind(mpg, disp) ~ qsec + wt + drat, data = mtcars[c(depVars, 
    indepVars)])

Coefficients:
             mpg       disp    
(Intercept)   11.3945  452.3407
qsec           0.9462  -20.3504
wt            -4.3978   89.9782
drat           1.6561  -41.1148

2) переформулировать @akrun и @Konrad, в комментариях под вопросом предложить использовать reformulate. Этот подход создает объект "formula", тогда как приведенные выше методы создают строку символов в качестве формулы. (Если бы это было необходимо для предыдущих решений, приведенных выше, можно было бы использовать fo <- formula(fo) .) Обратите внимание, что важно, чтобы аргумент ответа на reformulate был объектом вызова, а не строкой символов, иначе reformulate будет интерпретировать строку символов как имя одна переменная.

fo <- reformulate(indepVars, parse(text = sprintf("cbind(%s)", toString(depVars)))[[1]])
do.call("lm", list(fo, quote(mtcars)))

давая:

Call:
lm(formula = cbind(mpg, disp) ~ qsec + wt + drat, data = mtcars)

Coefficients:
             mpg       disp    
(Intercept)   11.3945  452.3407
qsec           0.9462  -20.3504
wt            -4.3978   89.9782
drat           1.6561  -41.1148

3) lm.fit Другой способ вообще не использовать формулу:

m <- as.matrix(mtcars)
fit <- lm.fit(cbind(1, m[, indepVars]), m[, depVars])

Вывод представляет собой список с этими компонентами:

> names(fit)
[1] "coefficients"  "residuals"     "effects"       "rank"         
[5] "fitted.values" "assign"        "qr"            "df.residual"  
person G. Grothendieck    schedule 01.02.2016