如果我没有误会您的意思,您正在使用这样的数据集:
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
。得到的线性模型除了通常的“lm”类之外还有一个额外的“mlm”类。我创建了一个特殊的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
and创建的那个“东西” paste0
。谢谢你。
因此,您正在对公式进行编程,或者想要在循环中动态生成/构造模型公式。有很多方法可以做到这一点,许多 Stack Overflow 问题都与此有关。通常有两种方法:
- 使用
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) ~ .
评论:
R 核心的其他地方也支持这个多 LHS 公式: