Newey-West标准误差与Mean Groups / Fama-MacBeth估计

时间:2015-10-24 23:09:16

标签: r regression standard-error

我正试图让Newey-West标准错误与pmg()包中的plm(Mean Groups / Fama-MacBeth估算器)的输出一起使用。

遵循here的示例:

require(foreign)
require(plm)
require(lmtest)
test <- read.dta("http://www.kellogg.northwestern.edu/faculty/petersen/htm/papers/se/test_data.dta")

fpmg <- pmg(y~x, test, index=c("firmid", "year")) # Time index in second position, unlike the example

我可以直接使用coeftest来获取Fama-MacBeth标准错误:

# Regular “Fama-MacBeth” standard errors
coeftest(fpmg)

# t test of coefficients:
#   
#             Estimate Std. Error t value Pr(>|t|)    
# (Intercept) 0.032470   0.071671   0.453   0.6505    
# x           0.969212   0.034782  27.866   <2e-16 ***
# ---
# Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

然而,试图使用纽维西估计师失败了:

# Newey-West standard-errors
coeftest(fpmg, vcov = NeweyWest(fpmg, lag=3))

# Error in UseMethod("estfun") : 
#   no applicable method for 'estfun' applied to an object of class "c('pmg', 'panelmodel')"

这似乎是plm包中的缺点。你知道一种让这项工作的方法吗?我应该为estfun个对象编写自己的pmg代码吗?从头开始编码Newey-West估算器?或者我应该完全绕过plm包裹?

2 个答案:

答案 0 :(得分:2)

目前使用plm包不可能实现此目的。

但是,您可以自己创建它们。

假设你有:

fpmg <- pmg(y~x, test, index = c('year', 'firmid'))
fpmg.coefficients <- fpmg$coefficients
# (Intercept)            x 
#  0.03127797   1.03558610 

coeftest(fpmg)
#             Estimate Std. Error t value Pr(>|t|)    
# (Intercept) 0.031278   0.023356  1.3392   0.1806    
# x           1.035586   0.033342 31.0599   <2e-16 ***

然后你可以像在下面那样简单地创建估算器:

the.years <- unique(test$year)
a.formula <- y ~ x


first.step <-  lapply(the.years, function(a.year) {
                temp.data <- test[test$year == a.year, ]
                an.lm <- lm(a.formula, data = temp.data)
                the.coefficients <- an.lm$coef
                the.results <- as.data.frame(cbind(a.year, t(the.coefficients)))
                the.results
                }) 

first.step.df <- do.call('rbind', first.step)

second.step.coefficients <- apply(first.step.df[, -1], 2, mean)
second.step.coefficients
# (Intercept)           x 
#  0.03127797  1.03558610 

identical(fpmg.coefficients, second.step.coefficients)
# [1] TRUE

以防万一,检查它们是否完全相同。 最后,你可以获得Newey-West(1987)的一个滞后调整t统计量的方法:

library(sandwich)
second.step.NW.sigma.sq <- apply(first.step.df[, -1], 2, 
                             function(x) sqrt(NeweyWest(lm(x ~ 1), 
                               lag = 1, prewhite = FALSE)['(Intercept)',       
                                 '(Intercept)']))
second.step.NW.sigma.sq
#  (Intercept)            x 
#   0.02438398   0.02859447
t.statistics.NW.lag.1 <- second.step.coefficients / second.step.NW.sigma.sq

t.statistics.NW.lag.1
# (Intercept)           x 
#    1.282726   36.216301

更新

在我的回答中,我只包含了t统计量的“手动”计算,因为它的计算速度更快。 更通用的解决方案是使用coeftest()包的lmtest函数对Newey-West校正的t统计量及其p值进行计算。

coeftest(lm(first.step.df$'(Intercept)' ~ 1), vcov = NeweyWest(lm(first.step.df$'(Intercept)' ~ 1), lag = 1, prewhite = FALSE))
# t test of coefficients:
#             Estimate Std. Error t value Pr(>|t|)
# (Intercept) 0.031278   0.024384  1.2827   0.2316
coeftest(lm(first.step.df$x ~ 1), vcov = NeweyWest(lm(first.step.df$x ~ 1), lag = 1, prewhite = FALSE))
# t test of coefficients:
#             Estimate Std. Error t value  Pr(>|t|)    
# (Intercept) 1.035586   0.028594  36.216 4.619e-11 ***

答案 1 :(得分:0)

我认为我们可以使用 tidyverse 来进行 Newey-West 调整,因为基础 R 方法过于冗长。三四年前,tidyverse还很不成熟,但是今天我们可以比较完美的使用tidyverse。这是 tidyverse 方法。此外,我的回答中使用了 broom 包。

# test data:
set.seed(1234)
a <- tibble(
            year = rep(1:20, each = 100),
            firmid = rep(1:100, times = 20),
            x1 = rnorm(2000),
            x2 = rnorm(2000),
            y = 2 + 3 * x1 - 2 * x2 + rnorm(1)
           )

Newey-West 调整:

a.formula <- formula("y ~ x1+x2")
lag <- 1

regco <- a %>% 
   group_by(year) %>%
   group_modify(~tidy(lm(a.formula, data = .x))) %>% 
   select(year,term,estimate) %>% 
   pivot_wider(names_from = term,
               values_from = estimate) %>% 
   ungroup() %>% 
   select(x1, x2, `(Intercept)`) %>% 
   map(
       ~coeftest(
                 lm(.x ~ 1), 
                 vcov = NeweyWest(
                                  lm(.x ~ 1), 
                                  lag = lag, 
                                  prewhite = FALSE
                                 )
                )
      )