Notation
Still assumes
\(y_{it} = \delta D_{it} + \gamma_{i} + \gamma_{t} + \epsilon_{it}\) for \(t=1,...,T\) and \(i=1,...,N\)
\(y_{it} = \delta D_{it} + \gamma_{i} + \gamma_{t} + \epsilon_{it}\) for \(t=1,...,T\) and \(i=1,...,N\)
Most common approach (default in most statistical software)
Equivalent to demeaned model: \[y_{it} - \bar{y}_{i} = \delta (D_{it} - \bar{D}_{i}) + (\gamma_{i} - \bar{\gamma}_{i}) + (\gamma_{t} - \bar{\gamma}_{t}) + (\epsilon_{it} - \bar{\epsilon}_{i})\]
\(\gamma_{i} - \bar{\gamma}_{i} = 0\) since \(\gamma_{i}\) is time-invariant
Requires strict exogeneity assumption (error is uncorrelated with \(D_{it}\) for all time periods)
\(y_{it} = \delta D_{it} + \gamma_{i} + \gamma_{t} + \epsilon_{it}\) for \(t=1,...,T\) and \(i=1,...,N\)
Instead of subtracting the mean, subtract the prior period values \[y_{it} - y_{i,t-1} = \delta(D_{it} - D_{i,t-1}) + (\gamma_{i} - \gamma_{i}) + (\gamma_{t} - \gamma_{t-1}) + (\epsilon_{it} - \epsilon_{i,t-1})\]
Requires exogeneity of \(\epsilon_{it}\) and \(D_{it}\) only for time \(t\) and \(t-1\) (weaker assumption than within estimator)
Sometimes useful to estimate both FE and FD just as a check
library(fixest)
library(modelsummary)
library(causaldata)
reg.dat <- causaldata::gapminder %>%
mutate(lgdp_pc=log(gdpPercap))
m1 <- feols(lifeExp ~ lgdp_pc | country, data=reg.dat)
modelsummary(list("Default FE"=m1),
shape=term + statistic ~ model,
gof_map=NA,
coef_rename=c("lgdp_pc"="Log GDP per Capita"))
Default FE | |
---|---|
Log GDP per Capita | 9.769 |
(0.702) |
library(lmtest)
reg.dat <- causaldata::gapminder %>%
group_by(country) %>%
mutate(lgdp_pc=log(gdpPercap),
lgdp_pc=lgdp_pc - mean(lgdp_pc, na.rm=TRUE),
lifeExp=lifeExp - mean(lifeExp, na.rm=TRUE))
m2 <- lm(lifeExp~ 0 + lgdp_pc , data=reg.dat)
modelsummary(list("Default FE"=m1, "Manual FE"=m2),
shape=term + statistic ~ model,
gof_map=NA,
coef_rename=c("lgdp_pc"="Log GDP per Capita"),
vcov = ~country)
Default FE | Manual FE | |
---|---|---|
Log GDP per Capita | 9.769 | 9.769 |
(0.702) | (0.701) |
Note: feols
defaults to clustering at level of FE, lm
requires our input
library(plm)
reg.dat <- causaldata::gapminder %>%
mutate(lgdp_pc=log(gdpPercap))
m3 <- plm(lifeExp ~ 0 + lgdp_pc, model="fd", index=c("country","year"), data=reg.dat)
modelsummary(list("Default FE"=m1, "Manual FE"=m2, "Default FD"=m3),
shape=term + statistic ~ model,
gof_map=NA,
coef_rename=c("lgdp_pc"="Log GDP per Capita"))
Default FE | Manual FE | Default FD | |
---|---|---|---|
Log GDP per Capita | 9.769 | 9.769 | 5.290 |
(0.702) | (0.284) | (0.291) |
reg.dat <- causaldata::gapminder %>%
mutate(lgdp_pc=log(gdpPercap)) %>%
group_by(country) %>%
arrange(country, year) %>%
mutate(fd_lifeexp=lifeExp - dplyr::lag(lifeExp),
lgdp_pc=lgdp_pc - dplyr::lag(lgdp_pc)) %>%
na.omit()
m4 <- lm(fd_lifeexp~ 0 + lgdp_pc , data=reg.dat)
modelsummary(list("Default FE"=m1, "Manual FE"=m2, "Default FD"=m3, "Manual FD"=m4),
shape=term + statistic ~ model,
gof_map=NA,
coef_rename=c("lgdp_pc"="Log GDP per Capita"))
Default FE | Manual FE | Default FD | Manual FD | |
---|---|---|---|---|
Log GDP per Capita | 9.769 | 9.769 | 5.290 | 5.290 |
(0.702) | (0.284) | (0.291) | (0.291) |
reg.dat2 <- causaldata::gapminder %>%
mutate(lgdp_pc=log(gdpPercap)) %>%
inner_join(reg.dat %>% select(country, year), by=c("country","year"))
m5 <- feols(lifeExp ~ lgdp_pc | country, data=reg.dat2)
modelsummary(list("Default FE"=m5, "Default FD"=m3, "Manual FD"=m4),
shape=term + statistic ~ model,
gof_map=NA,
coef_rename=c("lgdp_pc"="Log GDP per Capita"))
Default FE | Default FD | Manual FD | |
---|---|---|---|
Log GDP per Capita | 8.929 | 5.290 | 5.290 |
(0.741) | (0.291) | (0.291) |
Don’t want to read too much into this, but…
Want to estimate \(ATT = E[Y_{1}(1)- Y_{0}(1) | D=1]\)
Pre-Period | Post-Period | |
---|---|---|
Treatment | \(E(Y_{0}(0)|D=1)\) | \(E(Y_{1}(1)|D=1)\) |
Control | \(E(Y_{0}(0)|D=0)\) | \(E(Y_{0}(1)|D=0)\) |
Problem: We don’t see \(E[Y_{0}(1)|D=1]\)
Want to estimate \(ATT = E[Y_{1}(1)- Y_{0}(1) | D=1]\)
Pre-Period | Post-Period | |
---|---|---|
Treatment | \(E(Y_{0}(0)|D=1)\) | \(E(Y_{1}(1)|D=1)\) |
Control | \(E(Y_{0}(0)|D=0)\) | \(E(Y_{0}(1)|D=0)\) |
Strategy 1: Estimate \(E[Y_{0}(1)|D=1]\) using \(E[Y_{0}(0)|D=1]\) (before treatment outcome used to estimate post-treatment)
Want to estimate \(ATT = E[Y_{1}(1)- Y_{0}(1) | D=1]\)
Pre-Period | Post-Period | |
---|---|---|
Treatment | \(E(Y_{0}(0)|D=1)\) | \(E(Y_{1}(1)|D=1)\) |
Control | \(E(Y_{0}(0)|D=0)\) | \(E(Y_{0}(1)|D=0)\) |
Strategy 2: Estimate \(E[Y_{0}(1)|D=1]\) using \(E[Y_{0}(1)|D=0]\) (control group used to predict outcome for treatment)
Want to estimate \(ATT = E[Y_{1}(1)- Y_{0}(1) | D=1]\)
Pre-Period | Post-Period | |
---|---|---|
Treatment | \(E(Y_{0}(0)|D=1)\) | \(E(Y_{1}(1)|D=1)\) |
Control | \(E(Y_{0}(0)|D=0)\) | \(E(Y_{0}(1)|D=0)\) |
Strategy 3: DD
Estimate \(E[Y_{1}(1)|D=1] - E[Y_{0}(1)|D=1]\) using \(E[Y_{0}(1)|D=0] - E[Y_{0}(0)|D=0]\) (pre-post difference in control group used to predict difference for treatment group)
Key identifying assumption is that of parallel trends
\[E[Y_{0}(1) - Y_{0}(0)|D=1] = E[Y_{0}(1) - Y_{0}(0)|D=0]\]
\[\begin{align} E[Y_{1}(1) - Y_{0}(1)|D=1] &=& \left( E[Y(1)|D=1] - E[Y(1)|D=0] \right) \\ & & - \left( E[Y(0)|D=1] - E[Y(0)|D=0]\right) \end{align}\]
\[y_{it} = \alpha + \beta D_{i} + \lambda \times Post_{t} + \delta \times D_{i} \times Post_{t} + \varepsilon_{it}\]
Pre | Post | Post - Pre | |
---|---|---|---|
Treatment | \(\alpha + \beta\) | \(\alpha + \beta + \lambda + \delta\) | \(\lambda + \delta\) |
Control | \(\alpha\) | \(\alpha + \lambda\) | \(\lambda\) |
Diff | \(\beta\) | \(\beta + \delta\) | \(\delta\) |
Treated | Period | Mean |
---|---|---|
Control | Pre | 1.512192 |
Control | Post | 3.010816 |
Treated | Pre | 4.517785 |
Treated | Post | 12.026116 |
In this example:
So the ATT is 6.0097068
(1) | |
---|---|
dTRUE | 3.006 |
(0.028) | |
tTRUE | 1.499 |
(0.028) | |
dTRUE × tTRUE | 6.010 |
(0.040) |