library(dplyr)
library(fixest)
library(haven)
library(lmtest)
library(plm)
wagepan <- read_dta(
"https://empirical-economics.netlify.app/tutorials/datafiles/WAGEPAN.DTA"
)
# Between and within variation.
bind_rows(lapply(c("educ", "union", "married"), function(v) {
by_person <- wagepan |>
group_by(nr) |>
summarise(person_mean = mean(.data[[v]]),
within_sd = sd(.data[[v]]), .groups = "drop")
data.frame(
variable = v,
between_sd = sd(by_person$person_mean),
average_within_sd = mean(by_person$within_sd)
)
}))
f_all <- lwage ~ union + educ + black + hisp + exper + expersq + married
tv <- c("union", "exper", "expersq", "married")
model_vars <- c("lwage", "nr", "year", tv, "educ", "black", "hisp")
wagepan <- wagepan |>
filter(if_all(all_of(model_vars), ~ !is.na(.x)))
pooled <- plm(f_all, wagepan, index = c("nr", "year"), model = "pooling")
re <- plm(f_all, wagepan, index = c("nr", "year"), model = "random")
fe <- plm(f_all, wagepan, index = c("nr", "year"), model = "within")
wagepan_cre <- wagepan |>
group_by(nr) |>
mutate(across(all_of(tv), mean, .names = "mean_{.col}")) |>
ungroup()
cre <- feols(
lwage ~ union + exper + expersq + married + educ + black + hisp +
mean_union + mean_exper + mean_expersq + mean_married,
data = wagepan_cre, vcov = ~nr
)
# On a balanced panel, OLS on the person means is the between estimator.
wagepan_means <- wagepan |>
group_by(nr) |>
summarise(across(all_of(all.vars(f_all)[-1]), mean),
lwage = mean(lwage), .groups = "drop")
between <- lm(f_all, data = wagepan_means)
# The coefficients.
lapply(list(Between = between, Pooled = pooled, RE = re, FE = fe,
Mundlak = cre), function(m) coef(m)[c("union", "educ")])
# The standard errors to report.
V_between <- sandwich::vcovHC(between, type = "HC0")
V_pooled <- vcovHC(pooled, method = "arellano", type = "HC0",
cluster = "group")
V_re <- vcovHC(re, method = "arellano", type = "HC0",
cluster = "group")
V_fe <- vcovHC(fe, method = "arellano", type = "HC0",
cluster = "group")
coeftest(between, V_between)
coeftest(re, V_re)
coeftest(fe, V_fe)
coeftest(cre, vcov. = vcov(cre))
coeftest(pooled) # default standard errors
coeftest(pooled, V_pooled) # person-clustered standard errors