When units adopt treatment at different times, coresynth fits each
adoption cohort separately and aggregates the cohort
ATTs with weights proportional to N_treated × T_post
(Clarke et al. 2023):
All six estimators support this; staggered timing is detected automatically from the treatment column — no extra flag is needed.
A staggered panel
Here u1 is treated from period 11 and u2
from period 16.
set.seed(42)
N <- 12; TT <- 20
f <- cumsum(rnorm(TT, 0, 0.5))
lam <- rnorm(N, 1, 0.3)
dat <- expand.grid(time = seq_len(TT), id = paste0("u", seq_len(N)))
dat$y <- as.vector(outer(f, lam)) + rnorm(nrow(dat), 0, 0.3)
dat$d <- 0L
dat$d[dat$id == "u1" & dat$time > 10] <- 1L
dat$d[dat$id == "u2" & dat$time > 15] <- 1L
dat$y[dat$d == 1] <- dat$y[dat$d == 1] + 2.0 # true ATT = 2.0Fitting
fit <- scm_fit(y ~ d | id + time, data = dat, method = "sdid")
fit$estimate # aggregate ATT
#> [1] 1.872835
fit$staggered # TRUE
#> [1] TRUEPer-cohort detail is in cohort_estimates:
fit$cohort_estimates
#> cohort n_treated T_pre T_post estimate weight
#> 1 11 1 10 10 1.839381 0.6666667
#> 2 16 1 15 5 1.939744 0.3333333Choosing the control group
control_group controls which units serve as donors for
each cohort:
-
"clean"(default) — never-treated units plus not-yet-treated units (those adopting later than the current cohort). -
"never_treated"— never-treated units only.
Inference under staggered adoption
sdid_inference(), gsc_inference(), and
si_inference() all extend to staggered fits.
jackknife_global is the staggered-specific variant that
removes each unique control unit across all cohorts at
once, correctly capturing cross-cohort correlation.
library(broom)
tidy(sdid_inference(fit, method = "bootstrap", n_boot = 100, seed = 1))
#> term estimate std.error statistic p.value conf.low conf.high method
#> 1 ATT 1.872835 0.09273774 20.19496 1.084054e-90 1.711155 2.060448 bootstrap
#> alternative n_controls staggered
#> 1 two.sided 10.5 TRUE
tidy(sdid_inference(fit, method = "jackknife_global"))
#> term estimate std.error statistic p.value conf.low conf.high
#> 1 ATT 1.872835 0.1186042 15.79063 3.609468e-56 1.640375 2.105295
#> method alternative n_controls staggered
#> 1 jackknife_global two.sided 11 TRUENotes
-
plot()andaugment()for staggered fits operate per cohort; the aggregate synthetic series is not defined (Y_synth = NULL). - SCM staggered adoption supports
covariates =(partial-out) but not thepredictors = pred(...)interface. - SI additionally supports staggered and multi-arm simultaneously — see Estimators.
