如果我没有误会您的意思,您正在使用这样的数据集:
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))。我用pasteand创建的那个“东西” 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 公式: