使用贬值变量估算R(lm)中具有不同参数数量的方程

时间:2016-05-23 15:48:54

标签: r

我想估算一个等式:

Y = \alpha + \delta Z + \beta (X - \bar{X}) + \gamma Z (X - \bar{X})

(其中条形表示变量的平均值......意思是,我想自动在Z和贬值版本的X之间进行交互。到目前为止,我只是事先手动贬低变量并估算:

lm(Y ~ .*Z, data= sdata)

这似乎有效,但我宁愿使用不需要手动贬低的解决方案,因为我还希望包含更复杂术语的方法,例如:

Y = \alpha + \delta Z + \beta (A*X - \bar{A*X}) + \gamma Z (A*X - \bar{A*X})

修改 根据要求,一个有效的代码示例,请注意,实际上我有大量(和变化)数量的X变量,因此我不想使用硬编码变体:

x1 <- runif(100)
x2 <- runif(100)
Z  <- runif(100)
Y  <- exp(x1) + exp(x2) + exp(z)

##current way of estimating the first equation:
sdata <- data.frame(Y=Y,Z=Z,x1=x1-mean(x1),x2=x2-mean(x2))
lm(Y ~ .*Z, data= sdata)

##basically what I want is that the following terms, and their interactions with Z are also used: 
#  X1^2 - mean(X1^2)
#  X2^2 - mean(X2^2)
#  X1*X2 - mean(X1*X2)

编辑2: 现在,我想要实现的基本上是什么

lm(Y ~ .^2*Z, data= sdata)

会这样做。但是,给定之前的demeaing表达式,例如:Z:X1:X2对应于:(x1-mean(x1))*(x2-mean(x2)),而我想要的是x1*x2-mean(x1*x2)

1 个答案:

答案 0 :(得分:2)

要在公式中显示该比例:

lm(mpg ~ cyl + scale(disp*hp, scale=F), data=mtcars)

Call:
lm(formula = mpg ~ cyl + scale(disp * hp, scale = F), data = mtcars)

Coefficients:
                (Intercept)                          cyl  scale(disp * hp, scale = F)  
                  3.312e+01                   -2.105e+00                   -4.642e-05  

现在进行比较,让我们在公式之外缩放交互:

mtcars$scaled_interaction <- with(mtcars, scale(disp*hp, scale=F))

lm(mpg ~ cyl + scaled_interaction, data=mtcars)

Call:
lm(formula = mpg ~ cyl + scaled_interaction, data = mtcars)

Coefficients:
       (Intercept)                 cyl  scaled_interaction  
         3.312e+01          -2.105e+00          -4.642e-05  

至少在这些示例中,似乎公式内的scale正在起作用。

为您的具体问题提供解决方案:

备选方案1:使用公式

# fit without Z
mod <- lm(Y ~ (.)^2, data= sdata[, names(sdata) != "Z" ])
vars <- attr(mod$terms, "term.labels")
vars <- gsub(":", "*", vars) # needed so that scale works later
vars <- paste0("scale(", vars, ", scale=F)")
newf <- as.formula(paste0("Y ~ ", paste0(vars, collapse = "+")))
# now interact with Z
f2 <- update.formula(newf, . ~ .*Z)
# This fives the following formula:
f2  
  Y ~ scale(x1, scale = F) + scale(x2, scale = F) + scale(x1*x2, scale = F) + 
  Z + scale(x1, scale = F):Z + scale(x2, scale = F):Z + scale(x1*x2, scale = F):Z

备选方案2:使用模型矩阵

# again fit without Z and get model matrix
mod <- lm(Y ~ (.)^2, data= sdata[, names(sdata) != "Z" ])
modmat <- apply(model.matrix(mod), 2, function(x) scale(x, scale=F))

此处,所有x和相互作用都被贬低:

> head(modmat)
     (Intercept)         x1          x2       x1:x2
[1,]           0  0.1042908 -0.08989091 -0.01095459
[2,]           0  0.1611867 -0.32677059 -0.05425087
[3,]           0  0.2206845  0.29820499  0.06422944
[4,]           0  0.3462069 -0.15636463 -0.05571430
[5,]           0  0.3194451 -0.38668844 -0.12510551
[6,]           0 -0.4708222 -0.32502269  0.15144812

> round(colMeans(modmat), 2)
(Intercept)          x1          x2       x1:x2 
          0           0           0           0 

您可以按如下方式使用模型矩阵:

modmat <- modmat[, -1] # remove intercept
lm(sdata$Y ~ modmat*sdata$Z)

它不漂亮,但应该使用任意数量的解释变量。您还可以将YZ添加到矩阵中,以便输出看起来更漂亮(如果这是一个问题)。请注意,您也可以直接创建模型矩阵而无需拟合模型。我直接从装配好的模型中取出它,因为它已经适合第一种方法。

作为旁注,可能没有以更直接的方式实施,因为很难想象与贬值变量的相互作用相比,更有利于贬低相互作用的情况。

比较两种方法:

这里是两种方法的输出进行比较。如您所见,除系数名称外,一切都是相同的。

> lm(sdata$Y ~ modmat*sdata$Z)

Call:
lm(formula = sdata$Y ~ modmat * sdata$Z)

Coefficients:
        (Intercept)             modmatx1             modmatx2          modmatx1:x2              sdata$Z  
            4.33105              1.56455              1.43979             -0.09206              1.72901  
   modmatx1:sdata$Z     modmatx2:sdata$Z  modmatx1:x2:sdata$Z  
            0.25332              0.38155             -0.66292  

> lm(f2, data=sdata)

Call:
lm(formula = f2, data = sdata)

Coefficients:
                (Intercept)         scale(x1, scale = F)         scale(x2, scale = F)  
                    4.33105                      1.56455                      1.43979  
  scale(x1 * x2, scale = F)                            Z       scale(x1, scale = F):Z  
                   -0.09206                      1.72901                      0.25332  
     scale(x2, scale = F):Z  scale(x1 * x2, scale = F):Z  
                    0.38155                     -0.66292