使用R margin包复制Stata marginlist参数?

时间:2017-07-31 16:40:05

标签: r stata prediction marginal-effects

我无法在R中复制Stata margins命令的特定用例:   margins var1, over(var2) 我一直在尝试使用R中的margins包。

为了提供可重现的示例,我使用了mtcars数据集并将其从R导出到Stata中,因此我们在两个程序中使用相同的数据集:

R代码:

library(foreign)
library(margins)
write.dta(mtcars, “mtcars.dta")

Stata代码:

use "mtcars.dta", clear

在两个程序中创建示例线性回归模型

Stata代码:

quietly regress mpg cyl i.am c.wt##c.hp

R代码:

x <- lm(mpg ~ cyl + factor(am) + hp * wt, data = mtcars)

两个程序之间的模型输出(未显示)相同

比较模型中每个变量的平均边际效应表

Stata代码和输出:

margins, dydx(*)

Average marginal effects                          Number of obs   =         32
Model VCE: OLS

Expression   : Linear prediction, predict() dy/dx w.r.t. : cyl 1.am wt hp

------------------------------------------------------------------------------
             |            Delta-method
             |      dy/dx   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
         cyl |  -.3708001   .5293674    -0.70   0.490     -1.45893    .7173301
        1.am |  -.0709546   1.374981    -0.05   0.959    -2.897268    2.755359
          wt |  -3.868994   .9170145    -4.22   0.000    -5.753944   -1.984043
          hp |  -.0249882   .0120345    -2.08   0.048    -.0497254    -.000251
------------------------------------------------------------------------------ 
Note: dy/dx for factor levels is the discrete change from the base level.

R代码和输出:

xmarg <- margins(x)
summary(xmarg)

factor     AME     SE       z      p   lower   upper
    am1 -0.0710 1.3750 -0.0516 0.9588 -2.7659  2.6240
    cyl -0.3708 0.5294 -0.7005 0.4836 -1.4083  0.6667
     hp -0.0250 0.0120 -2.0764 0.0379 -0.0486 -0.0014
     wt -3.8690 0.9170 -4.2191 0.0000 -5.6663 -2.0717

如您所见,这两个输出非常相似,正如预期的那样使用R margins包。

问题1:边际预测超过变量值

Stata代码和输出:

margins, over(cyl)

Predictive margins                                Number of obs   =         32
Model VCE: OLS

Expression   : Linear prediction, predict()
over         : cyl

------------------------------------------------------------------------------
             |            Delta-method
             |     Margin   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
         cyl |
          4  |   26.56699   .6390379    41.57   0.000     25.25342    27.88055
          6  |   20.04662   .5797511    34.58   0.000     18.85492    21.23831
          8  |   15.02406   .5718886    26.27   0.000     13.84853    16.19959
------------------------------------------------------------------------------

R代码和输出:

aggregate(fitted~cyl, data = xmarg, FUN = mean)
  cyl   fitted
1   4 26.56699
2   6 20.04662
3   8 15.02406

在上面的两个例子中,R和Stata之间的边际预测是相同的。但是,有没有一种方法(手动不做)为每个边际预测生成delta方法标准误差,如上面的Stata表所示?

问题2:特定变量的边际预测:

Stata代码和输出:

margins am

Predictive margins                                Number of obs   =         32
Model VCE    : OLS

Expression   : Linear prediction, predict()

------------------------------------------------------------------------------
             |            Delta-method
             |     Margin   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
          am |
          0  |   20.11945   .6819407    29.50   0.000      18.7177     21.5212
          1  |    20.0485   .9052764    22.15   0.000     18.18767    21.90932
------------------------------------------------------------------------------

R代码和输出:

aggregate(fitted~am, data = xmarg, FUN = mean)
  am   fitted
1  0 17.14737
2  1 24.39231

在这个例子中,我们试图通过在预测之后对数据集进行子集化来复制margins命令中的Stata的“marginlist”参数。这似乎不是正确的方法。我们如何从Stata复制这些结果?

问题3:一个变量对另一个变量的边际预测

复制此结果是我的主要目标!

Stata代码和输出

margins am, over(cyl)

Predictive margins                                Number of obs   =         32
Model VCE    : OLS

Expression   : Linear prediction, predict()
over         : cyl

------------------------------------------------------------------------------
             |            Delta-method
             |     Margin   Std. Err.      t    P>|t|     [95% Conf. Interval]
-------------+----------------------------------------------------------------
      cyl#am |
        4 0  |   26.61859   1.246074    21.36   0.000     24.05725    29.17993
        4 1  |   26.54763   .7034599    37.74   0.000     25.10165    27.99362
        6 0  |   20.07703   .6449805    31.13   0.000     18.75125     21.4028
        6 1  |   20.00607   1.144518    17.48   0.000     17.65348    22.35866
        8 0  |    15.0342   .6228319    24.14   0.000     13.75395    16.31445
        8 1  |   14.96324   1.257922    11.90   0.000     12.37754    17.54894
------------------------------------------------------------------------------

R代码和输出:

aggregate(fitted ~ am + cyl, data = xmarg, FUN = mean)
  am cyl   fitted
1  0   4 22.83306
2  1   4 27.96721
3  0   6 19.06359
4  1   6 21.35732
5  0   8 15.08720
6  1   8 14.64519

正如您所看到的,点数估计现在大不相同,而且没有SE表。解决上面的问题1和问题2可能会解决问题3。

2 个答案:

答案 0 :(得分:3)

对于这些问题,您需要预测软件包,该软件包是保证金的一部分。目前尚无法获得平均预测的标准误差,但至少可以使用以下方法获得与Stata相同的平均预测。

关于Stata的margins命令的主要直觉如下:

margins x1

等同于

margins, at(x1 = (...))

其中...x1的所有可能值。这些表达式中的任一个都会生成反事实数据集,其中x1对于数据中的所有情况都固定为给定值,然后对该数据集的该临时反事实版本执行模型预测。

over()选项是一个子设置过程:

margins, over(x1)

根据x1的值拆分数据,然后对每个子集执行模型预测。您可以将其与at结合使用,但是考虑起来有些奇怪。例如:

margins, over(x1) at(x2 = (1 2))

将所有观察值的x2固定为1,然后将数据除以x1,然后为每个子集生成预测,并将其平均。然后针对反事实版本重复此操作,其中所有观察值的x2都设置为2。

在R中,prediction::prediction()将使用at()参数为您提供at的等效项。通过将数据子集传递给over()参数,它也将为您提供data的等效项。

因此,对于您的问题2

> prediction::prediction(x, at = list(am = c(0,1)))
Average predictions for 32 observations:
 at(am) value
      0 20.12
      1 20.05

对于您的问题3

> prediction::prediction(x, at = list(am = c(0,1)), data = subset(mtcars, cyl == 4))
Average predictions for 11 observations:
 at(am) value
      0 26.62
      1 26.55
> prediction::prediction(x, at = list(am = c(0,1)), data = subset(mtcars, cyl == 6))
Average predictions for 7 observations:
 at(am) value
      0 20.08
      1 20.01
> prediction::prediction(x, at = list(am = c(0,1)), data = subset(mtcars, cyl == 8))
Average predictions for 14 observations:
 at(am) value
      0 15.03
      1 14.96

在这两种情况下,都不能仅通过执行predict(x)并汇总预测来复制Stata的输出,因为预测发生在反事实数据集上。

同样,目前尚未实现差异(截至2018年8月)。

答案 1 :(得分:1)

我遇到了同样的问题,并且发现了以下解决方法。该线程当然是一个旧的线程。但是我认为将其添加到该线程中后,我的解决方案会更容易找到。

我已经模拟了因变量“ dv”的数据,这些变量由变量“ level”和“ treat”解释,以及它们之间的相互作用。

  1. 数据模拟

    N <- 1000 uid <- rep(1:N) treat <- rep(1:10, each = N/10) level <- rep(1:100, each = N/100) err <- rnorm(N, 0, 1) hdv <- 40 + 2 * treat + .25 * level - .05 * treat * level + err dv <- ifelse(hdv > 47, 1, 0) dat <- data.frame(dv = dv, treat = treat, level = level, hdv = hdv)

  2. 估算

由于因变量是二进制的,因此我估算了Logit模型。众所周知,Logit中的交互项(如在任何非线性模型中)不能直接解释。这就是为什么我想要“水平”而不是“治疗”的边际效应。

logit <- glm(dv ~ treat*level, family = binomial(link = "logit"), data = dat)
  1. 边际影响

R可以在设置数据子集时实际上以置信区间恢复边际效应,如

hmpr7 <- summary(margins(logit, variables = "level", data = dat[dat$treat == 7,]))

以下是所有治疗方法的一种(涉及某种方式):

hmpr <- list()
for (i in 1:10) {
  hmpr[[i]] <- summary(margins(logit, variables = "level", data = dat[dat$treat == i,]))
}
# the result is a list. For further use it is transformed into a data.frame
mpr <- data.frame(matrix(unlist(hmpr), nrow=length(hmpr), byrow=T))
# in this process, all variables are classified as factors. This is changed here
mpr <- data.frame(lapply(mpr, function(x) as.numeric(as.character(x))))
# only the variables of interest for the graph are kept
mpr <- mpr[,c(2, 6, 7)]
# meaningful names are assigned to the variables
mpr <- setNames(mpr, c("pred", "lower", "upper")) 
# treatment classifier is added to rows
mpr$treat <- rep(1:10)
  1. 对结果进行绘图(如Stata的marginsplot)

    `plot(mpr $ pred〜mpr $ treat,  ylim = range(c(mpr $ lower,mpr $ upper)),  pch = 19,xlab =“处理”,ylab =“边际效应+ 95%CI”,  main =“每次治疗水平的边际效应”)

    箭头(mpr $ treat,mpr $ lower,    mpr $ treat,mpr $ upper,    长度= .05,角度= 90,代码= 3)

    abline(h = 0,col =“ red”)`