如果我没有理解错的话,您正在使用这样的数据集:
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
and 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
and $fitted.values
是矩阵。除了通常的“lm”类之外,生成的线性模型还有一个附加的“mlm”类。我创建了一个特殊的mlm /questions/tagged/mlm标签收集有关该主题的一些问题,并按其总结tag wiki https://stackoverflow.com/tags/mlm/info.
如果您有更多协变量,您可以使用以下方法避免键入或粘贴公式.
:
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
Caution:不要写
y1 + y2 + y3 ~ x1 + x2 + x3
这将治疗y = y1 + y2 + y3
作为单个响应。使用cbind()
.
跟进:
我对概括感兴趣。我有一个数据框df
,其中首先n
列是因变量(y1,y2,y3,....)
接下来m
列是自变量(x1+x2+x3+....)
. For n = 3
and m = 3
it is 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 问题都与此有关。通常有两种方法:
-
use reformulate https://stackoverflow.com/q/12967797/4891738;
- use
paste
/ paste0
and formula
/ as.formula
.
我更喜欢reformulate
然而,为了简洁,它不支持公式中的多个 LHS。如果要改造LHS还需要一些特殊处理 https://stackoverflow.com/q/26374106/4891738。所以在下面我会使用paste
解决方案。
为您提供数据框df
,你可以这样做
paste0("cbind(", paste(names(df)[1:n], collapse = ", "), ")", " ~ .")
一个更好看的方法是使用sprintf
and 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
, as lm
会自动将其强制转换为公式类。或者你可以使用自己进行强制formula
(or as.formula
):
formula(string_formula)
# cbind(Sepal.Length, Sepal.Width) ~ .
Remark:
R 核心的其他地方也支持这个多重 LHS 公式:
-
函数的公式法aggregate https://stackoverflow.com/q/41075121/4891738;
-
方差分析aov https://stackoverflow.com/q/51937380/4891738.