6.11 Two way fixed effect (TWFE) Revisited
We have already seen the TWFE and its importance in accounting for unobserved heterogeneity. The TWFE is heavily linked to the difference-in-differences setting (perhaps mistakenly). However, note that the TWFE estimator is not equal to the DiD estimator unless the treatment effects are homogeneous across both units and time.
\[\begin{equation} \label{eq:TWFE} Y_{it} = \theta_{t} + \eta_{i} + \alpha D_{it} + v_{it} \;.....TWFE \end{equation}\]
Here, \(Y_{it}\) is the outcome of individual \(i\) in period \(t\) (\(t \in \{1,\;2,\;...,\;T\}\))
\(\theta_{t}\) is the time fixed effects; \(\eta_{i}\) is the unit fixed effect
\(D_{it}\) captures whether individual \(i\) is treated in time \(t\)
Equation above is the TWFE.
In two groups and two-period setting, the above equation can be estimated in a number of different ways. Let’s simulate data to look.
Assign treatment effect = 20
Data Arrange 1: Demeaning to get rid of \(\eta_i\) from TWFE equation (Within Estimator)
Let’s look at the concept behind the within estimator. In the two-period two-group case, TWFE can be written as: \[\begin{equation} Y_{i1} = \theta_{1} + \eta_{i} + \alpha D_{i1} + v_{i1} \nonumber \\ Y_{i2} = \theta_{2} + \eta_{i} + \alpha D_{i2} + v_{i2} \end{equation}\]
where, \(i\) is represented by 1 (treatment group) and 0 (untreated group).
Adding the sub-equations and dividing by the number of time period \((T=2)\) yields: \[\begin{equation} \frac{Y_{i1}+Y_{i2}}{2} = \frac{\theta_{1}+\theta_{2}}{2} + \frac{2\eta_{i}}{2} + \frac{\alpha (D_{i1}+D_{i2})}{2} + \frac{v_{i1}+v_{i2}}{2} \\ Y_{i} = \frac{\theta_{1}+\theta_{2}}{2} + \eta_{i} + \alpha D_{i} + v_{i} \nonumber \end{equation}\]
Substracting the above equation from the TWFE yields the following: \[\begin{equation} Y_{it}-Y_{i} = \theta_{t} - \frac{\theta_{1}+\theta_{2}}{2} + \alpha (D_{it}-D_i) + (v_{it}-v_i) \end{equation}\]
The code shows data arranging for the within estimator.
###########################
# Treatment group
###########################
<- rep(1, 1000)
treat_t <- rep(c(0, 1), each = 500)
period_t <- rep(seq(1, 500, 1), 2) #for the panel nature of data
id <- 20 * period_t + 7 + rnorm(1000, 0, 5)
y_treat <- data.frame(treat = treat_t, period = period_t, Y = y_treat, id = id)
treatdata <- treatdata %>% mutate(Ytrans = Y - mean(Y),
treatdata D = treat * period - mean(treat * period))
##########################
# control group
##########################
<- rep(0, 1000)
control_t <- rep(c(0, 1), each = 500)
period_c <- rep(seq(501, 1000, 1), 2)
id <- 3 + rnorm(1000, 0, 5)
y_control = data.frame(treat = control_t, period = period_c, Y = y_control, id = id)
controldata <- controldata %>% mutate(Ytrans = Y - mean(Y),
controldata D = treat * period - mean(treat * period))
= rbind(treatdata, controldata) data
Data Arrange 2: First differencing
Let’s briefly look at the concept behind first differencing. Write TWFE as: \[\begin{equation} Y_{i1} = \theta_{1} + \eta_{i} + \alpha D_{i1} + v_{i1} \nonumber \\ Y_{i2} = \theta_{2} + \eta_{i} + \alpha D_{i2} + v_{i2} \end{equation}\]
for \(i \in \{0,\;1\}\).
Then, \[\begin{equation} Y_{i2} - Y_{i1} = \theta_{2} - \theta_{1} + \alpha (D_{i2}-D_{i1}) + (v_{i2} - v_{i1}) \end{equation}\]
The code shows data arranging for the first difference estimator.
# First the treated group
<- treatdata %>% filter(period == 0) %>% dplyr::select(-c("Ytrans"))
fd_treat1 colnames(fd_treat1) <- c("treat1", "period1", "Y1", "id")
<- treatdata %>% filter(period == 1)%>% dplyr::select(-c("Ytrans"))
fd_treat2 colnames(fd_treat2) <- c("treat2", "period2", "Y2", "id")
<- merge(fd_treat1, fd_treat2, by = "id", all.x = T)
fd_treat <- fd_treat %>% mutate(Y_FD = Y2 - Y1,
fd_treat D = (period2 * treat2) - (period1 * treat1))
# Then the control group
<- controldata %>% filter(period == 0) %>% dplyr::select(-c("Ytrans"))
fd_control1 colnames(fd_control1) <- c("treat1", "period1", "Y1", "id")
<- controldata %>% filter(period == 1)%>% dplyr::select(-c("Ytrans"))
fd_control2 colnames(fd_control2) <- c("treat2", "period2", "Y2", "id")
<- merge(fd_control1, fd_control2, by = "id", all.x = T)
fd_control <- fd_control %>% mutate(Y_FD = Y2 - Y1,
fd_control D = (period2 * treat2) - (period1 * treat1))
= rbind(fd_treat, fd_control) FDdata