使用多个LHS拟合线性模型

时间:2016-09-01 04:03:14

标签: r regression linear-regression lm mlm

我是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 个答案:

答案 0 :(得分:11)

如果我没有弄错你,你正在使用这样的数据集:

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循环的成本就可以忽略不计。用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”类。我创建了一个特殊的标记,收集了有关该主题的一些问题,并通过其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 <- lm(cbind(y1, y2, y3) ~ ., data = dat))。但是如何使用df的结构自动执行此操作。我的意思是(for i in (1:n)) fit <- lm(cbind(df[something] ~ df[something], data = dat))。我用pastepaste0创建的“东西”。谢谢。

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

  1. use reformulate;
  2. 使用paste / paste0formula / as.formula
  3. 我更喜欢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) ~ .
    

    <强>注:

    这个多LHS公式也在R core的其他地方得到支持: