R中负二项式回归的稳健标准误差与Stata的误差不匹配

时间:2018-12-05 09:29:08

标签: r stata standards standard-error robust

我正在R中复制一个负二项式回归模型。在计算鲁棒标准误差时,输出与标准误差的Stata输出不匹配。

原始的Stata代码是

nbreg displaced  eei lcostofwar cfughh roadskm lpopdensity ltkilled, robust nolog

我尝试了手动计算,也尝试了vcovHC中的sandwich。但是,两者都不会产生相同的结果。

我的回归模型如下: mod1 <- glm.nb(displaced ~ eei + costofwar_log + cfughh + roadskm + popdensity_log + tkilled_log, data = mod1_df)

我使用vcovHC尝试了从HC0HC5的每个选项。 尝试1:

cov_m1 <- vcovHC(mod1, type = "HC0", sandwich = T)
se <- sqrt(diag(cov_m1))

尝试2:

mod1_rob <- coeftest(mod1, vcovHC = vcov(mod1, type = "HC0"))

最成功的是HC0vcov = sandwich,但没有SE是正确的。

有什么建议吗?

编辑

我的输出如下(使用HC0):

                 Estimate Std. Error z value  Pr(>|z|)    
(Intercept)     1.3281183  1.5441312  0.8601  0.389730    
eei            -0.0435529  0.0183359 -2.3753  0.017536 *  
costofwar_log   0.2984376  0.1350518  2.2098  0.027119 *  
cfughh         -0.0380690  0.0130254 -2.9227  0.003470 ** 
roadskm         0.0020812  0.0010864  1.9156  0.055421 .  
popdensity_log -0.4661079  0.1748682 -2.6655  0.007688 ** 
tkilled_log     1.0949084  0.2159161  5.0710 3.958e-07 ***

我要复制的Stata输出为:

                 Estimate Std. Error    
(Intercept)     1.328     1.272
eei            -0.044     0.015 
costofwar_log   0.298     0.123  
cfughh         -0.038     0.018 
roadskm         0.002     0.0001   
popdensity_log -0.466     0.208 
tkilled_log     1.095     0.209  

找到数据集here,重新编码的变量为:

mod1_df <- table %>% 
  select(displaced, eei_01, costofwar, cfughh, roadskm, popdensity, 
tkilled)
mod1_df$popdensity_log <- log(mod1_df$popdensity + 1)
mod1_df$tkilled_log <- log(mod1_df$tkilled + 1)
mod1_df$costofwar_log <- log(mod1_df$costofwar + 1)
mod1_df$eei <- mod1_df$eei_01*100

2 个答案:

答案 0 :(得分:2)

在R中,您需要手动提供自由度校正,因此请尝试我从this source借来的方法:

dfa <- (G/(G - 1)) * (N - 1)/pm1$df.residual

# display with cluster VCE and df-adjustment
firm_c_vcov <- dfa * vcovHC(pm1, type = "HC0", cluster = "group", adjust = T)
coeftest(pm1, vcov = firm_c_vcov)

这里G是数据集中的面板数,N是观察数,pm1是您的模型估计值。显然,您可以删除群集。

答案 1 :(得分:2)

Stata使用观察到的Hessian进行计算,glm.nb()使用期望的Hessian。因此,bread()函数使用的默认sandwich()是不同的,从而导致不同的结果。还有其他一些R包使用观察到的hessian进行方差-协方差估计(例如gamlss),但是这些R包没有为estfun()包提供sandwich方法。

因此,下面我简单地设置一个专用的bread_obs()函数,该函数从negbin对象中提取ML估计值,设置负对数似然率,并通过{{1} },然后从中计算出“面包”(省略log(theta)的估算值):

numDeriv::hessian()

使用该功能,我可以将bread_obs <- function(object, method = "BFGS", maxit = 5000, reltol = 1e-12, ...) { ## data and estimated parameters Y <- model.response(model.frame(object)) X <- model.matrix(object) par <- c(coef(object), "log(theta)" = log(object$theta)) ## dimensions n <- NROW(X) k <- length(par) ## nb log-likelihood nll <- function(par) suppressWarnings(-sum(dnbinom(Y, mu = as.vector(exp(X %*% head(par, -1))), size = exp(tail(par, 1)), log = TRUE))) ## covariance based on observed Hessian rval <- numDeriv::hessian(nll, par) rval <- solve(rval) * n rval[-k, -k] } 的输出(基于预期的粗麻布)与使用sandwich()的输出(基于观察到的粗麻布)进行比较。

bread_obs()

与Stata相比仍存在细微差异,但可能是优化等方面的数值差异。

如果您为s_exp <- sandwich(mod1) s_obs <- sandwich(mod1, vcov = bread_obs) cbind("Coef" = coef(mod1), "SE (Exp)" = sqrt(diag(s_exp)), "SE (Obs)" = sqrt(diag(s_obs))) ## Coef SE (Exp) SE (Obs) ## (Intercept) 1.328 1.259 1.259 ## eei -0.044 0.017 0.015 ## costofwar_log 0.298 0.160 0.121 ## cfughh -0.038 0.015 0.018 ## roadskm 0.002 0.001 0.001 ## popdensity_log -0.466 0.135 0.207 ## tkilled_log 1.095 0.179 0.208 个对象创建新的专用bread()方法

negbin

然后,如果您进行bread.negbin <- bread_obs ,则方法分派将使用此方法。