拟合具有多个 LHS 的线性模型

Posted

技术标签:

【中文标题】拟合具有多个 LHS 的线性模型【英文标题】:Fitting a linear model with multiple LHS 【发布时间】:2017-01-08 19:22:11 【问题描述】:

我是 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))

x1x2x3 是协变量,y1y2y3 是三个独立的响应。您正在尝试拟合三个线性模型:

y1 ~ x1 + x2 + x3
y2 ~ x1 + x2 + x3
y3 ~ x1 + x2 + x3

目前您正在使用循环通过y1y2y3,每次拟合一个模型。您希望通过将 for 循环替换为 lapply 来加快该过程。

你走错了路。lm() 是一项昂贵的操作。只要您的数据集不小,for 循环的成本就可以忽略不计。用lapply 替换for 循环不会带来性能提升。

由于所有三个模型的 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 标签,收集有关该主题的一些问题,并通过其tag 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 = 3m = 3,它是fit &lt;- lm(cbind(y1, y2, y3) ~ ., data = dat))。但是如何通过使用df 的结构来自动执行此操作。我的意思是(for i in (1:n)) fit &lt;- lm(cbind(df[something] ~ df[something], data = dat))。我用pastepaste0 创建的那个“东西”。谢谢。

因此,您正在对公式进行编程,或者想要在循环中动态生成/构造模型公式。有很多方法可以做到这一点,许多 Stack Overflow 问题都与此有关。通常有两种方法:

    use reformulate; 使用paste/paste0formula/as.formula

我更喜欢reformulate,因为它的简洁性,但是,它不支持公式中的多个 LHS。 It also needs some special treatment if you want to transform the LHS。所以在下面我会使用paste 解决方案。

对于你的数据框df,你可以这样做

paste0("cbind(", paste(names(df)[1:n], collapse = ", "), ")", " ~ .")

更美观的方法是使用sprintftoString 来构造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 公式:

the formula method for function aggregate; ANOVA analysis with aov

【讨论】:

我应该强调glm不能做多个LHS。 GLM 迭代地拟合重新加权的线性回归,其中权重取决于响应变量。显然,两个不同的 LHS 会给出两组不同的权重,因此会有两个不同的加权模型矩阵。然后不可能进行常见的 QR 分解。一个非常相似的场景是Run lm with multiple responses and weights。

以上是关于拟合具有多个 LHS 的线性模型的主要内容,如果未能解决你的问题,请参考以下文章

拟合贝叶斯线性回归并预测不可观察的值

spss非线性回归分析步骤

[机器学习与scikit-learn-32]:算法-回归-普通线性模型拟合非线性分布数据-分箱

以下回归模型中属于线性回归模型的都有哪些

R语言使用lm函数拟合回归模型(简单线性回归一元回归simple regression)并解读拟合模型

拟合线性回归模型中的值误差