Подгонка линейной модели с несколькими LHS
Я новичок в R и хочу улучшить следующий скрипт с *apply
функция (я читал о apply
, но я не смог его использовать). Я хочу использовать lm
функция на нескольких независимых переменных (которые являются столбцами в кадре данных). я использовал
for (i in (1:3) {
assign(paste0('lm.',names(data[i])), lm(formula=formula(i),data=data))
}
Formula(i)
определяется как
formula=function(x)
{
as.formula ( paste(names(data[x]),'~', paste0(names(data[-1:-3]), collapse = '+')), env=parent.frame() )
}
Спасибо.
1 ответ
Если я не ошибаюсь, вы работаете с таким набором данных:
set.seed(0)
dat <- data.frame(y1 = rnorm(30), y2 = rnorm(30), y3 = rnorm(30),
x1 = rnorm(30), x2 = rnorm(30), x3 = rnorm(30))
x1
, x2
а также x3
являются ковариатами, и y1
, y2
, y3
три независимых ответа. Вы пытаетесь подогнать три линейные модели:
y1 ~ x1 + x2 + x3
y2 ~ x1 + x2 + x3
y3 ~ x1 + x2 + x3
В настоящее время вы используете цикл y1
, y2
, y3
примерка одной модели за раз. Вы надеетесь ускорить процесс, заменив for
цикл с lapply
,
Вы на неправильном пути. lm()
это дорогая операция. Пока ваш набор данных не мал, затраты на for
Цикл незначительный. Замена for
цикл с lapply
не дает прироста производительности.
Так как у вас есть тот же RHS (правая сторона ~
) для всех трех моделей матрица модели одинакова для трех моделей. Следовательно, QR-факторинг для всех моделей необходимо выполнить только один раз. lm
позволяет это, и вы можете использовать:
fit <- lm(cbind(y1, y2, y3) ~ x1 + x2 + x3, data = dat)
#Coefficients:
# y1 y2 y3
#(Intercept) -0.081155 0.042049 0.007261
#x1 -0.037556 0.181407 -0.070109
#x2 -0.334067 0.223742 0.015100
#x3 0.057861 -0.075975 -0.099762
Если вы проверите str(fit)
вы увидите, что это не список из трех линейных моделей; вместо этого, это одна линейная модель с одним $qr
объект, но с несколькими LHS. Так $coefficients
, $residuals
а также $fitted.values
являются матрицами. Полученная линейная модель имеет дополнительный класс "mlm" помимо обычного класса "lm". Я создал специальный тэг mlm, собрав несколько вопросов по теме, которые обобщены тегом wiki.
Если у вас гораздо больше ковариат, вы можете избежать ввода или вставки формулы, используя .
:
fit <- lm(cbind(y1, y2, y3) ~ ., data = dat)
#Coefficients:
# y1 y2 y3
#(Intercept) -0.081155 0.042049 0.007261
#x1 -0.037556 0.181407 -0.070109
#x2 -0.334067 0.223742 0.015100
#x3 0.057861 -0.075975 -0.099762
Внимание: не пишите
y1 + y2 + y3 ~ x1 + x2 + x3
Это будет относиться y = y1 + y2 + y3
в качестве одного ответа. использование cbind()
,
Следовать за:
Я заинтересован в обобщении. У меня есть фрейм данных
df
где первыйn
столбцы являются зависимыми переменными(y1,y2,y3,....)
и следующийm
столбцы являются независимыми переменными(x1+x2+x3+....)
, Заn = 3
а такжеm = 3
этоfit <- lm(cbind(y1, y2, y3) ~ ., data = dat))
, Но как сделать это автоматически, используя структуруdf
, Я имею в виду что-то вроде(for i in (1:n)) fit <- lm(cbind(df[something] ~ df[something], data = dat))
, Это "что-то" я создал это сpaste
а такжеpaste0
, Спасибо.
Таким образом, вы программируете свою формулу или хотите динамически генерировать / создавать формулы модели в цикле. Есть много способов сделать это, и многие вопросы переполнения стека об этом. Обычно есть два подхода:
- использование
reformulate
; - использование
paste
/paste0
а такжеformula
/as.formula
,
я предпочитаю reformulate
однако из-за аккуратности он не поддерживает несколько формул LHS в формуле. Это также требует особого отношения, если вы хотите трансформировать LHS. Так что в следующем я бы использовал paste
решение.
Для вас фрейм данных df
, вы можете сделать
paste0("cbind(", paste(names(df)[1:n], collapse = ", "), ")", " ~ .")
Более привлекательный способ - использовать sprintf
а также toString
построить LHS:
sprintf("cbind(%s) ~ .", toString(names(df)[1:n]))
Вот пример использования iris
Набор данных:
string_formula <- sprintf("cbind(%s) ~ .", toString(names(iris)[1:2]))
# "cbind(Sepal.Length, Sepal.Width) ~ ."
Вы можете передать эту формулу строки lm
, как lm
автоматически приведёт его в класс формулы. Или вы можете сделать принуждение самостоятельно, используя formula
(или же as.formula
):
formula(string_formula)
# cbind(Sepal.Length, Sepal.Width) ~ .
Примечание:
Эта множественная формула LHS также поддерживается в другом месте в ядре R:
- метод формулы для функции
aggregate
; - ANOVA анализ с
aov
,