Event-Study extension of Synthetic Difference-in-Differences for R.
This is an R port of the Stata
sdid_event
package by Diego Ciccia, Damian Clarke, and Daniel Pailañir, which
implements the event-study decomposition of
Ciccia, Clarke, Pailañir (2024). The
underlying SDID estimator is
Arkhangelsky, Athey, Hirshberg, Imbens, Wager (2021, AER);
this package delegates the estimator to the
synthdid R package and
implements only the event-study decomposition on top.
# install.packages("remotes")
remotes::install_github("awhobbs/sdidevent")The synthdid dependency is on GitHub (not CRAN):
remotes::install_github("synth-inference/synthdid")library(sdidevent)
library(synthdid)
data(california_prop99)
setup <- panel.matrices(california_prop99)
est <- sdid_event(setup$Y, setup$N0, setup$T0,
vce = "bootstrap", breps = 200, seed = 1)
print(est)
plot(est)Output (truncated):
Event-Study Synthetic Difference-in-Differences
N0 = 38 controls, N1 = 1 treated
T0 = 19 pre periods, T1 = 12 post periods
Inference: bootstrap (B = 200, ci_method = normal)
Aggregate ATT: -15.6038 (SE = ~9.9)
vce |
Default? | What it does |
|---|---|---|
"bootstrap" |
Yes | Cluster bootstrap (matches Stata default). |
"placebo" |
Random treatment permutation among never-treated clusters. | |
"jackknife" |
Leave-one-out. Unit-level by default; cluster-level if cluster is supplied. |
|
"off" |
No inference; only point estimates. |
For state-level treatment assignment, pass cluster = state_vec (a
length-N vector aligned with the rows of Y). This activates cluster
bootstrap or cluster jackknife.
sdid_event_panel() auto-detects staggered adoption (multiple distinct
first-treated periods) from the long-form treatment indicator:
library(sdidevent)
# `df` has columns unit, year, y, treat where `treat` switches on at
# different years for different units.
est <- sdid_event_panel(df, outcome = "y", unit = "unit", time = "year",
treatment = "treat",
vce = "bootstrap", breps = 500, seed = 1)
print(est)
print(est$cohort_summary) # per-cohort N_tr, N_post, cohort_attFor matrix entry, pass a length-N integer vector for T0 giving each
unit's adoption period (NA for never-treated controls):
# 12 never-treated controls, 3 units adopting at t = 6, 3 at t = 10.
cohort_of <- c(rep(NA, 12), rep(6, 3), rep(10, 3))
est <- sdid_event(Y, N0 = 12, T0 = cohort_of,
vce = "bootstrap", breps = 500, seed = 1)The per-cohort decomposition follows Ciccia, Clarke, Pailañir (2024)
equations 3, 4, 6, 7 and matches Stata sdid_event to ~1e-6 on point
ATTs; see inst/extdata/staggered_stata_golden.csv for the reference
output.
-
Cluster-jackknife with the Cameron-Gelbach-Miller (2008)
small-cluster SE and
$t(G-1)$ reference distribution. Not in the Stata package. - Standard R conventions:
coef(),vcov(),plot(),summary()S3 methods. ggplot2-based event-study chart. -
keep_draws = TRUEexposes the raw bootstrap matrix for downstream inference (e.g., joint CIs).
If you use this package, please cite both the methodology and the port:
@article{ciccia2024short,
title = {A Short Note on Event-Study Synthetic Difference-in-Differences Estimators},
author = {Ciccia, Diego and Clarke, Damian and Pailañir, Daniel},
journal = {arXiv preprint arXiv:2407.09565},
year = {2024}
}
@article{arkhangelsky2021synthetic,
title = {Synthetic Difference-in-Differences},
author = {Arkhangelsky, Dmitry and Athey, Susan and Hirshberg, David A and
Imbens, Guido W and Wager, Stefan},
journal = {American Economic Review},
volume = {111},
number = {12},
pages = {4088--4118},
year = {2021}
}
@manual{hobbs2026sdidevent,
title = {sdidevent: Event-Study Synthetic Difference-in-Differences},
author = {Hobbs, Andrew},
year = {2026},
note = {R package version 0.2.0}
}GPL-3. See LICENSE.md.