Permutation inference on the aggregate effect when more than one unit is treated, following Abadie & L'Hour (2021, S.3.2). Each treated unit contributes its own test statistic; the identities of the treated units are then reassigned at random among all units, and the sum of the ranks of the real treated units' statistics is compared with its permutation distribution.
Arguments
- fit
A
coresynthobject fromscm_fit()withmethod = "scm"and more than one treated unit.- B
Number of treatment reassignments.
- statistic
Per-unit statistic to rank.
"mspe_ratio"(default) is the post/pre MSPE ratio of Abadie, Diamond & Hainmueller (2010), which adjusts for how well each unit was fitted;"effect"is the mean post-treatment gap and"abs_effect"its absolute value.- alternative
"two.sided"(default),"greater", or"less".- seed
Seed for the reassignment draw, so the p-value is reproducible without consuming the caller's RNG state.
Value
An object of class c("scm_rank_test", "coresynth_inference") with
p_value, statistic (the observed rank sum), rank_sums (its
permutation distribution), unit_statistics, n_treated, B and
alternative.
Details
Ranking is what makes the test usable here. mspe_ratio_pval() compares one
treated unit against placebo runs on single donors, which breaks down as
soon as the treated series is an average: the average is less noisy than any
single donor, so its pre/post MSPE ratio is inflated and the test rejects
far too often. Ranks sidestep that, because every statistic entering the
comparison, real or permuted, is computed on a single unit.
The fit must expose per-unit effects, so a staggered fit has to be made with
pool_cohorts = FALSE. A sharp fit with several treated units pools them by
design, and its per-unit statistics are computed here from the stored
per-unit series.
References
Abadie, A., & L'Hour, J. (2021). A penalized synthetic control estimator for disaggregated data. JASA, 116(536), 1817-1834.
See also
mspe_ratio_pval() for the single-treated-unit test.
Examples
set.seed(1)
panel <- expand.grid(unit = 1:12, year = 1:20)
panel$treated <- as.integer(panel$unit <= 3 & panel$year > 12)
panel$gdp <- panel$unit + 0.4 * panel$year +
rnorm(nrow(panel)) + 2 * panel$treated
fit <- scm_fit(gdp ~ treated | unit + year, data = panel, method = "scm")
#> predictors = NULL: using the outcome in each of the 12 pre-treatment periods as predictors (outcomes-only SCM).
scm_rank_pval(fit, B = 50)
#> === SCM rank-based permutation test ===
#> Treated units : 3 | donors: 9
#> Statistic : mspe_ratio
#> Reassignments : 50
#> Rank sum : 91
#> p-value : 0.0784 (two.sided)
