6.9 The \(2 \times 2\) Difference-in-Differences Estimate

Now that we’ve disscussed the difference-in-differences framework (mostly canonical DiD), we would like to look at various ways of estimating DiD. As we’ve seen, (a canonical) DiD estimation can simply be done non-parametrically by using the appropriate differences in means. Another way to do it is by using the regression framework, which provides several advantages including but not limited to: \(i)\) estimation of standard errors; \(ii)\) ease of accounting for necessary covariates; and \(iii)\) feasible estimation of DiD with multiple treatment groups with staggered treatment.

Let’s begin with the canonical DiD framework using the regression format. I’m going to set it up as the following:

\[\begin{equation} \label{eq:DiD_reg} Y_{it} = \alpha + \tau Post_{it} \times D_{i} + \sigma Post_{it} + \eta D_{i} + \epsilon_{it} \end{equation}\]

Let’s rewrite the DiD estimator from before as:

\(\tau_{did} = \underbrace{E[Y_{11} - Y_{10} | D = 1]}_{first\; difference} - \underbrace{E[Y_{01} - Y_{00} | D = 0]}_{second\; difference}\)

We’d want to see whether estimation of \(\tau\) in the regression above uncovers the DiD estimate. Let’s look at the following conditional expectations.

1). expected outcome for treated group post treatment: \(E(Y | D = 1, Post = 1) = \alpha + \tau + \sigma + \eta\)

2). expected outcome for treated group pre treatment: \(E(Y | D = 1, Post = 0) = \alpha + \eta\)

3). expected outcome for control group post treatment: \(E(Y | D = 0, Post = 1) = \alpha + \sigma\)

4). expected outcome for control group pre treatment: \(E(Y | D = 0, Post = 0) = \alpha\)

If you do the math, the first difference is given as \(\tau + \sigma\) and the second difference is \(\sigma\). The DiD – the difference between the first and the second difference – is \(\tau\). Hence, the estimation of \(\tau\), in the regression framework above, is the DiD estimate.

Let’s apply this to our ACA-Medicaid example.

# lets create the post, treat, and the interaction between the post and treat (labeled as did)
dat_canonical  <- dat_canonical  %>% 
                      mutate(post = ifelse(year >= 2014, 1, 0), 
                             treat = ifelse(expand == 1, 1, 0), 
                             did = post * treat)

reg_did  <- lm(sahieunins138 ~ did + post + treat, data = dat_canonical)
summary(reg_did)
## 
## Call:
## lm(formula = sahieunins138 ~ did + post + treat, data = dat_canonical)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -25.2196  -5.1221  -0.7641   4.7804  26.7359 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  41.4641     0.1890  219.41   <2e-16 ***
## did          -5.8134     0.4126  -14.09   <2e-16 ***
## post         -4.7840     0.2673  -17.89   <2e-16 ***
## treat        -7.8445     0.2918  -26.89   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 7.655 on 5650 degrees of freedom
## Multiple R-squared:  0.425,  Adjusted R-squared:  0.4247 
## F-statistic:  1392 on 3 and 5650 DF,  p-value: < 2.2e-16
did  <- naive - naive_pre
print(did)
## [1] -5.813426

Note that the difference in mean did and the regression coefficient on the interaction between \(Post \times treat\) are the same. Plus, we get the standard errors as well. Of course, the standard errors are not adjusted for clustering. The errors of observations within a cluster (the ground at which the treatment is implemented, in our case state) will be correlated, so we need to account for it. The way to do it is to cluster the standard error at the state level. This can be done using the fixest library and feols command.

reg_did_cluster  <- feols(sahieunins138 ~ did + post + treat, data = dat_canonical, cluster = ~state.abb)
summary(reg_did_cluster)
## OLS estimation, Dep. Var.: sahieunins138
## Observations: 5,654
## Standard-errors: Clustered (state.abb) 
##             Estimate Std. Error   t value   Pr(>|t|)    
## (Intercept) 41.46411   2.041183  20.31376  < 2.2e-16 ***
## did         -5.81343   1.266824  -4.58898 3.6981e-05 ***
## post        -4.78400   0.278769 -17.16117  < 2.2e-16 ***
## treat       -7.84455   2.612190  -3.00305 4.3962e-03 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## RMSE: 7.65276   Adj. R2: 0.424736

Note that the did coefficient remains unchanged. However, the standard error is inflated after clustering the errors at the state level.