估计三重交互的边际效应

Estimate marginal effect in triple interaction

我有一个具有三重交互的模型,类似于:

m1 <- lm(mpg ~ am*cyl*hp, mtcars)

我试图展示 am 的效果如何根据 cylhp 的条件而变化。使用 effects 库中的 Effect() 函数,我可以显示 mpg 的预测值。这对我的数据集运行良好且速度相当快。但是,我想显示每种情况下点之间的差距大小。

library(effects)
p1 <- as.data.frame(Effect(m1, focal.predictors = c("am", "cyl", "hp"), xlevels = list(am=c(0, 1), cyl=c(4,8), hp = c(100, 200))))

library(ggplot2)
ggplot(p1, aes(cyl, fit, color = as.factor(am))) +
  geom_point(position = position_dodge(0.5)) +
  geom_errorbar(aes(ymin=lower, ymax=upper), width = 0, position = position_dodge(0.5)) +
  facet_grid(~hp)

我尝试使用 margins 库中的 margins() 函数。如下所示。这显示了平均边际效应 (AME),我想这就是我想要展示的。但是,我的数据集花费了大量时间,因为我控制了与年份和一个自变量相互作用的国家/地区固定效应。

p2 <- margins(m1, at=list(cyl = c(4, 8), hp = c(100, 200)), variables = "am")
p2 <- summary(p2)

ggplot(p2, aes(cyl, AME, color = as.factor(hp))) +
  geom_point(position = position_dodge(0.5)) +
  geom_errorbar(aes(ymin=lower, ymax=upper), width = 0, position = position_dodge(0.5))

有什么方法可以使用 Effect() 来显示预测值之间的估计差距?

制作所需情节的所有相关信息都在 Effect() 函数的输出中。首先,我们 运行 模型并生成效果对象。

library(effects)
#> Loading required package: carData
#> lattice theme set by effectsTheme()
#> See ?effectsTheme for details.
library(ggplot2)
data(mtcars)

m1 <- lm(mpg ~ am*cyl*hp + wt + drat, mtcars)
E <- Effect(m1, 
            focal.predictors = c("am", "cyl", "hp"), 
            xlevels = list(am=c(0, 1), 
                           cyl=c(4,8), 
                           hp = seq(52, 335, length=10)))
p1 <- as.data.frame(E)

现在,要获得 am == 0am == 1 之间的差异,我们需要在数据框中识别这些值 p1

w0 <- which(p1$am == 0)
w1 <- which(p1$am == 1)

然后我们可以制作一个矩阵,我们将使用它来产生效果的差异。我们将它初始化为全零值,它需要有 nrow(p1) 行和 length(w0) 列:

D <- matrix(0, nrow = nrow(p1), ncol = length(w0))

现在,每一列对应于 am == 0am == 1 预测值之间的差异,具体值为 hpcal。对于 am == 0 的值,我们需要矩阵具有 -1 值,对于 am == 1,我们需要它具有值 1。我们可以按如下方式完成此操作:

D[cbind(w0, 1:ncol(D))] <- -1
D[cbind(w1, 1:ncol(D))] <- 1

然后我们可以这样得到差异:

diffs <- c(t(p1$fit) %*% D)

为了确保我们得到正确的数字,让我们看一下 diffs 的前两个值:

diffs[1:2]
#> [1]  3.2716241 -0.8526864
p1[1:4, ]
#>   am cyl hp      fit       se     lower    upper
#> 1  0   4 52 24.74134 2.784239 18.967181 30.51550
#> 2  1   4 52 28.01296 2.203560 23.443061 32.58287
#> 3  0   8 52 19.12017 3.466758 11.930556 26.30979
#> 4  1   8 52 18.26749 4.455793  9.026738 27.50823
p1$fit[2]-p1$fit[1]
#> [1] 3.271624
p1$fit[4]-p1$fit[3]
#> [1] -0.8526864

您可以看到 diffs 的前两个值与我们从 p1 计算的值相同。现在,我们需要计算差异的方差,我们可以这样做:

v_diffs <- t(D) %*% vcov(E) %*% D

接下来,我们制作一个数据集,让我们能够绘制出这些差异。我们将数据保存在 am == 0 的位置,这样我们就不会为每次比较复制行。然后,我们添加差异、标准误差和置信区间。

p11 <- p1[p1$am == 0, ]
p11$diff <- diffs
p11$se_diff <- sqrt(diag(v_diffs))
p11$lwr <- p11$diff - 1.96*p11$se_diff
p11$upr <- p11$diff + 1.96*p11$se_diff

然后,我们就可以制作剧情了。现在,对于 hpcyl 的每个不同值,每个点代表 am==0am==1 之间的差异:

ggplot(p11, aes(x=hp, y=diff, ymin=lwr, ymax=upr)) + 
  geom_pointrange() + 
  geom_hline(yintercept=0, linetype=2, col="red") + 
  facet_wrap(~as.factor(cyl)) + 
  theme_bw() + 
  theme(panel.grid=element_blank())

reprex package (v2.0.1)

创建于 2022-06-01

这是一个使用 the marginaleffects package 的替代方案,它被设计为 margins 的“继承者”,具有更大的灵活性,支持更多的模型类型,并且通常 更快。 (免责声明:我是作者。)

library(marginaleffects)

m <- lm(mpg ~ am*cyl*hp, mtcars)

plot_cme(m, effect = "am", condition = c("hp", "cyl"))

自定义绘图 ggplot2:

library(ggplot2)

plot_cme(m, effect = "am", condition = c("hp", "cyl"), draw = FALSE) |>
    ggplot(aes(condition1, dydx, ymin = conf.low, ymax = conf.high)) +
    geom_ribbon(alpha = .2) +
    geom_line() +
    facet_wrap(~condition2) +
    theme_classic()

只是数字结果:

mfx <- marginaleffects(m)
summary(mfx, by = "cyl")
#> Average marginal effects 
#>   Term cyl   Effect Std. Error z value  Pr(>|z|)    2.5 %    97.5 %
#> 1   am   6  2.00971    1.95284  1.0291 0.3034237 -1.81779  5.837211
#> 2   am   4  5.08709    1.76482  2.8825 0.0039453  1.62811  8.546073
#> 3   am   8  2.15232    2.23291  0.9639 0.3350919 -2.22410  6.528733
#> 4  cyl   6 -0.94326    0.71546 -1.3184 0.1873742 -2.34554  0.459026
#> 5  cyl   4 -2.06503    0.85842 -2.4056 0.0161455 -3.74751 -0.382553
#> 6  cyl   8  0.47177    1.71136  0.2757 0.7828002 -2.88243  3.825974
#> 7   hp   6 -0.05691    0.02592 -2.1956 0.0281202 -0.10772 -0.006108
#> 8   hp   4 -0.09174    0.03417 -2.6852 0.0072497 -0.15870 -0.024776
#> 9   hp   8 -0.03583    0.01893 -1.8930 0.0583573 -0.07293  0.001267
#> 
#> Model type:  lm 
#> Prediction type:  response