\[ \begin{split} \tau_{DID} &= [\mathbb{E}(Y_i| G_i = 1, T_i = 1) - \mathbb{E}(Y_i| G_i = 1, T_i = 0)] \\ &- [\mathbb{E}(Y_i| G_i = 0, T_i = 1) - \mathbb{E}(Y_i| G_i = 0, T_i = 0)]. \end{split} \]
\[ \begin{split} \tau_{DID} &= [\mathbb{E}(Y_i| G_i = 1, T_i = 1) - \mathbb{E}(Y_i| G_i = 1, T_i = 0)]\\ &- [\mathbb{E}(Y_i| G_i = 0, T_i = 1) - \mathbb{E}(Y_i| G_i = 0, T_i = 0)]\\ &= [\mathbb{E}(Y_i(1)| G_i = 1, T_i = 1) - \mathbb{E}(Y_i(0)| G_i = 1, T_i = 0)]\\ &- [\mathbb{E}(Y_i(0)| G_i = 0, T_i = 1) - \mathbb{E}(Y_i(0)| G_i = 0, T_i = 0)]\\ &+ [\mathbb{E}(Y_i(0)|G_i = 1, T_i = 1) - \mathbb{E}(Y_i(0)|G_i = 1, T_i = 1)]\\ &= \mathbb{E}(Y_i(1)| G_i = 1, T_i = 1) - \mathbb{E}(Y_i(0)|G_i = 1, T_i = 1)\\ &+ [\mathbb{E}(Y_i(0)|G_i = 1, T_i = 1) - \mathbb{E}(Y_i(0)| G_i = 1, T_i = 0)]\\ &- [\mathbb{E}(Y_i(0)| G_i = 0, T_i = 1) - \mathbb{E}(Y_i(0)| G_i = 0, T_i = 0)], \end{split} \] - \(\tau_{DID}\) is the average treatment effect on \(G_i = 1, T_i = 1\) plus the difference in the trends between two groups.
\[ \begin{split} \tau_{DID} &= \mathbb{E}(Y_{i1} - Y_{i0}| G_i = 1) - \mathbb{E}(Y_{i1} - Y_{i0}| G_i = 0). \end{split} \] - We can estimate this parameter as a two-way fixed-effect estimator \(\hat{\tau}_{DID}\) of: \[ Y_{it} = \mu_i + \lambda_t + \tau \cdot G_i \cdot t + \epsilon_{it}. \]
\[ \begin{split} \tau_{DID} &= \mathbb{E}(Y_{i1} - Y_{i0}| G_i = 1) - \mathbb{E}(Y_{i1} - Y_{i0}| G_i = 0)\\ &= \mathbb{E}(Y_{i1}(1) - Y_{i0}(0)| G_i = 1) - \mathbb{E}(Y_{i1}(0) - Y_{i0}(0)| G_i = 0)\\ &+ \mathbb{E}(Y_{i1}(0) - Y_{i1}(0)|G_i = 1)\\ &= \mathbb{E}(Y_{i1}(1) - Y_{i1}(0)| G_i = 1)\\ &+ \mathbb{E}(Y_{i1}(0) - Y_{i0}(0)|G_i = 1) - \mathbb{E}(Y_{i1}(0) - Y_{i0}(0)| G_i = 0). \end{split} \]
The parallel trend assumption in the panel case is: \[ \mathbb{E}(Y_{i1}(0) - Y_{i0}(0)|G_i = 1) = \mathbb{E}(Y_{i1}(0) - Y_{i0}(0)| G_i = 0). \]
This holds when: \[ Y_{it}(1) - Y_{it}(0) \perp\!\!\!\!\perp G_i. \]
Under this assumption, the DID parameter is the average treatment effect on treated: \[ \tau_{DID} = \mathbb{E}(Y_{i1}(1) - Y_{i0}(0)| G_i = 1). \]
\[ \begin{split} &= \mathbb{E}\Bigg[\frac{G_i - p(X_i)}{p(X_i) \cdot [1 - p(X_i)]} \cdot (Y_{i1} - Y_{i0}) \cdot \frac{p(X_i)}{\mathbb{P}(G_i = 1)} \Bigg]\\ &= \frac{1}{\mathbb{P}(G_i = 1)} \mathbb{E}\Bigg[\frac{G_i - p(X_i)}{1 - p(X_i)} \cdot (Y_{i1} - Y_{i0}) \Bigg]. \end{split} \]
set.seed(1)
N <- 1000
T <- 2
tau <- 10
f <- function(x) {
y <- x
return(y)
}
g <- function(x) {
y <- exp(x)
return(y)
}
df_i <-
tibble::tibble(
i = 1:N,
x = rnorm(length(i)),
v = rnorm(length(i)),
d = (runif(length(i)) < exp(g(x)) / (1 + exp(g(x))) ) %>% as.integer()
)
df <-
tidyr::expand_grid(i = 1:N, t = 0:(T - 1)) %>%
dplyr::left_join(df_i, by = "i") %>%
dplyr::mutate(
e_0 = rnorm(length(i)),
e_1 = rnorm(length(i)),
y_0 = f(x) * t + e_0,
y_1 = tau + x + f(x) * t + e_1,
y = (1 - d) * y_0 + d * (1 - t) * y_0 + d * t * y_1
)
df %>% modelsummary::datasummary_skim()
| Unique (#) | Missing (%) | Mean | SD | Min | Median | Max | ||
|---|---|---|---|---|---|---|---|---|
| i | 1000 | 0 | 500.5 | 288.7 | 1.0 | 500.5 | 1000.0 | |
| t | 2 | 0 | 0.5 | 0.5 | 0.0 | 0.5 | 1.0 | |
| x | 1000 | 0 | -0.0 | 1.0 | -3.0 | -0.0 | 3.8 | |
| v | 1000 | 0 | -0.0 | 1.0 | -3.3 | -0.0 | 3.6 | |
| d | 2 | 0 | 0.7 | 0.4 | 0.0 | 1.0 | 1.0 | |
| e_0 | 2000 | 0 | 0.0 | 1.0 | -3.7 | 0.0 | 3.1 | |
| e_1 | 2000 | 0 | -0.0 | 1.0 | -3.2 | -0.0 | 3.6 | |
| y_0 | 2000 | 0 | 0.0 | 1.3 | -4.6 | 0.0 | 4.4 | |
| y_1 | 2000 | 0 | 10.0 | 1.9 | 2.6 | 10.0 | 18.9 | |
| y | 2000 | 0 | 3.8 | 5.3 | -4.0 | 0.8 | 18.9 |
df %>% dplyr::mutate(t = as.factor(t)) %>% ggplot(aes(x = x, y = d, color = t, group = t)) + geom_smooth(method = "gam", formula = y ~ s(x, bs = "cs"), se = FALSE) + scale_color_viridis_d() + theme_classic()
df %>% dplyr::mutate(t = as.factor(t)) %>% ggplot(aes(x = x, y = y_0, color = t, group = t)) + geom_point() + scale_color_viridis_d() + theme_classic()
df %>% dplyr::mutate(t = as.factor(t)) %>% ggplot(aes(x = x, y = y_1, color = t, group = t)) + geom_point() + scale_color_viridis_d() + theme_classic()
df %>% dplyr::mutate(t = as.factor(t)) %>% dplyr:::mutate(tau_i = y_1 - y_0) %>% ggplot(aes(x = x, y = tau_i, color = t, group = t)) + geom_point() + scale_color_viridis_d() + theme_classic()
df %>% dplyr::filter(t == 1, d == 1) %>% dplyr::summarise(mean(y_1 - y_0))
## # A tibble: 1 x 1 ## `mean(y_1 - y_0)` ## <dbl> ## 1 10.2
model_twfe <-
lfe::felm(
data = df,
formula = y ~ d:t | i + t
)
modelsummary::modelsummary(model_twfe)
| Model 1 | |
|---|---|
| d × t | 10.709 |
| (0.171) | |
| Num.Obs. | 2000 |
| R2 | 0.951 |
| R2 Adj. | 0.901 |
model_ordid <-
DRDID::ordid(data = df, yname = "y", tname = "t",
idname = "i",dname = "d", xformla = ~ x
)
summary(model_ordid)
## Call: ## DRDID::ordid(yname = "y", tname = "t", idname = "i", dname = "d", ## xformla = ~x, data = df) ## ------------------------------------------------------------------ ## Outcome-Regression DID estimator for the ATT: ## ## ATT Std. Error t value Pr(>|t|) [95% Conf. Interval] ## 9.9773 0.1336 74.6829 0 9.7154 10.2391 ## ------------------------------------------------------------------ ## Estimator based on panel data. ## Outcome regression est. method: OLS. ## Analytical standard error. ## ------------------------------------------------------------------ ## See Sant'Anna and Zhao (2020) for details.
model_ipwdid <-
DRDID::ipwdid(data = df, yname = "y", tname = "t",
idname = "i",dname = "d", xformla = ~ x
)
summary(model_ipwdid)
## Call: ## DRDID::ipwdid(yname = "y", tname = "t", idname = "i", dname = "d", ## xformla = ~x, data = df) ## ------------------------------------------------------------------ ## IPW DID estimator for the ATT: ## ## ATT Std. Error t value Pr(>|t|) [95% Conf. Interval] ## 10.273 0.1308 78.5239 0 10.0165 10.5294 ## ------------------------------------------------------------------ ## Estimator based on panel data. ## Hajek-type IPW estimator (weights sum up to 1). ## Propensity score est. method: maximum likelihood. ## Analytical standard error. ## ------------------------------------------------------------------ ## See Sant'Anna and Zhao (2020) for details.
model_drdid <-
DRDID::drdid(data = df, yname = "y", tname = "t",
idname = "i",dname = "d", xformla = ~ x
)
summary(model_drdid)
## Call: ## DRDID::drdid(yname = "y", tname = "t", idname = "i", dname = "d", ## xformla = ~x, data = df) ## ------------------------------------------------------------------ ## Further improved locally efficient DR DID estimator for the ATT: ## ## ATT Std. Error t value Pr(>|t|) [95% Conf. Interval] ## 9.9616 0.1366 72.9093 0 9.6938 10.2294 ## ------------------------------------------------------------------ ## Estimator based on panel data. ## Outcome regression est. method: weighted least squares. ## Propensity score est. method: inverse prob. tilting. ## Analytical standard error. ## ------------------------------------------------------------------ ## See Sant'Anna and Zhao (2020) for details.