I'm trying to get Newey-West standard errors to work with the output of pmg()
(Mean Groups/Fama-MacBeth estimator) from the plm
package.
Following the example from 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
I can use coeftest
directly just fine to get the Fama-MacBeth standard errors:
# 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
However, trying to use the Newey-West estimators fails:
# 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')"
This seems like a shortcoming in the plm
package. Do you know a way to make this work? Should I code my own estfun
for pmg
objects? Code a Newey-West estimator from scratch? Or should I bypass the plm
package altogether?
Newey-West standard error method is a robust method/estimator which is very accurate when there is presence of heteroskedasticity and autocorrelation. Also, when in the panel model there is a lagged value of an indicator then this method is very consistent.
The Newey–West variance estimator handles autocorrelation up to and including a lag of m, where m is specified by stipulating the lag() option. Thus, it assumes that any autocorrelation at lags greater than m can be ignored.
Newey-West estimators adjust how the standard errors of the regression coefficients are calculated, but not the standard error of the model (eg. square root of the mean square error).
Currently this is impossible with plm
package.
However, you could just create them yourself.
Suppose you have:
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 ***
Then you can simply create the estimators yourself like in:
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
Check that they are identical both ways just in case. Last, you can obtain the Newey-West (1987) with one lag adjusted t-statistics for the means with:
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
In my answer, I had only included the "manual" calculation of the t-statistic, because it is computationally faster.
A more generic solution is to calculcate the Newey-West corrected t-statistics and their p-values with the coeftest()
function of the lmtest
package.
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 ***
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With