Compute sample size, power, or minimum detectable effect (MDE) for a two-group, two-period difference-in-differences (DiD) contrast.
Usage
power_did(treat, ...)
# Default S3 method
power_did(
treat,
control,
...,
outcome = c("mean", "prop"),
var = NULL,
sd = NULL,
effect = NULL,
n = NULL,
power = 0.8,
alpha = 0.05,
N = Inf,
deff = 1,
resp_rate = 1,
alternative = c("two.sided", "one.sided"),
ratio = 1,
overlap = 0,
overlap_cor = 0,
plan = NULL
)Arguments
- treat
Numeric length-2 vector for treated group outcomes:
c(baseline, endline).- ...
Additional arguments passed to methods. Unused arguments are rejected.
- control
Numeric length-2 vector for control group outcomes:
c(baseline, endline).- outcome
Outcome scale:
"mean"(default) or"prop".- var
Outcome variance. Applies to
outcome = "mean"only; underoutcome = "prop"the cell variances follow fromtreatandcontrol, so supplying it is an error rather than a silent no-op. Length 1: common variance for all four cells. Length 2: group-specific variancesc(var_treat, var_control), assumed equal across waves. Length 4: cell-specific variances in orderc(var_treat_baseline, var_treat_endline, var_control_baseline, var_control_endline).- sd
Outcome standard deviation, an alternative spelling of
vartaking the same lengths. Supply at most one ofvarorsd.- effect
Absolute DiD effect size to detect (> 0). Defaults to the contrast implied by
treatandcontrol,|(treat[2] - treat[1]) - (control[2] - control[1])|, so it only needs to be supplied to plan for an effect other than the one those paths describe. Supplying a value that disagrees with them warns. LeaveNULLwith bothnandpowergiven to solve for the MDE.- n
Per-arm sample size per wave. Scalar (equal treated/control) or length-2 vector
c(n_treat, n_control). LeaveNULLto solve for n.- power
Target power, in (0, 1). Leave
NULLto solve for power.- alpha
Significance level, default 0.05.
- N
Population size for finite-population correction. A scalar applies to both arms. Use a length-2 vector
c(N_treat, N_control)for arm-specific population sizes.Inf(default) disables FPC.- deff
Design effect multiplier (> 0).
- resp_rate
Expected response rate, in (0, 1]. Default 1 (no adjustment). The required sample size is inflated by
1 / resp_rate.- alternative
Character:
"two.sided"(default) or"one.sided". Use"two.sided"when the intervention could plausibly move the outcome in either direction (the usual default). Use"one.sided"when only one direction is of interest, which requires a smaller sample for the same power.- ratio
Allocation ratio
n_treat / n_control(default 1). Used only when solving forn(n = NULL).- overlap
Panel overlap fraction in [0, 1] within each arm across baseline and endline.
- overlap_cor
Correlation between baseline and endline outcomes within overlapping units, in [0, 1].
- plan
Optional
svyplan()object providing design defaults.
Value
A svyplan_power object with components:
nPer-arm sample size (scalar or length-2).
powerAchieved power.
effectDiD effect size.
type"did_prop"or"did_mean".solvedWhich quantity was solved for (
"n","power", or"mde").paramsList of input parameters.
Details
treat and control already determine the contrast, so effect is
optional: leave n or power as NULL to solve for it. Leaving both
n and power supplied while effect is NULL solves for the MDE
instead. Exactly one quantity must remain unknown.
The DiD estimand is
(treat_endline - treat_baseline) - (control_endline - control_baseline).
Per-arm variance of the before-after change accounts for panel overlap:
$$V_{\text{arm}} = V_{\text{pre}} + V_{\text{post}} - 2 \cdot \text{overlap} \cdot \rho \cdot \sqrt{V_{\text{pre}} \cdot V_{\text{post}}}$$
The DiD test statistic variance is then:
$$V_d = \text{deff} \left( \frac{V_{\text{trt}} \cdot \text{fpc}_t}{n_t} + \frac{V_{\text{ctrl}} \cdot \text{fpc}_c}{n_c} \right)$$
When overlap = 0, this reduces to the classical flat-variance formula.
What treat and control are used for
Both paths always supply the contrast. Whether they also supply the
variance depends on outcome: for "prop" the four cell variances are
\(p(1-p)\) at each path value, while for "mean" the variance comes
entirely from var and the paths are used for the contrast alone.
Because the contrast is derived, effect is redundant with the paths and
is only needed to plan for a different effect than they describe, for
example a conservative target below the change a pilot observed. Doing so
warns, since the printed result then shows an effect that the displayed
paths do not produce.
Normal approximation
Critical values and power come from the standard normal, with the
variance treated as known and no degrees-of-freedom correction, as in
power_mean() and power_prop(). The cluster count, not the unit
count, is what governs the accuracy of that approximation for a
clustered DiD design: deff inflates the variance but does not model
the loss of degrees of freedom, so a design with few clusters per arm
is optimistic here by more than the unit count suggests.
The df argument that n_prop(), n_mean() and n_alloc() accept has
no counterpart here, and its absence is a decision rather than an
omission. There the quantile is the half-width of a confidence interval
and a t quantile substitutes for a normal one directly; here it is a
normal deviate for an alternative, and a t-based power calculation is a
different procedure. Passing df is an error that says so.
References
Valliant, R., Dever, J. A., & Kreuter, F. (2018). Practical Tools for Designing and Weighting Survey Samples (2nd ed.). Springer. Chapter 4.
See also
power_prop() for two-sample proportions, power_mean() for
two-sample means.
Examples
# DiD sample size for means. The effect is the contrast the two paths
# describe: (55 - 50) - (52 - 50) = 3.
power_did(
treat = c(50, 55), control = c(50, 52),
outcome = "mean", var = 100
)
#> Power analysis for DiD means (solved for sample size)
#> n = 349 (per group), power = 0.800, effect = 3.0000
#> (treat = (50.000, 55.000), control = (50.000, 52.000), alpha = 0.05, deff = 1, var = (100.00, 100.00, 100.00, 100.00))
# DiD power for proportions
power_did(
treat = c(0.30, 0.36), control = c(0.30, 0.33),
outcome = "prop", effect = 0.03, n = 800, power = NULL
)
#> Power analysis for DiD proportions (solved for power)
#> n = 800 (per group), power = 0.149, effect = 0.0300
#> (treat = (0.300, 0.360), control = (0.300, 0.330), alpha = 0.05, deff = 1)
# MDE for means with n = 500
power_did(
treat = c(50, 55), control = c(50, 52),
outcome = "mean", var = 100, effect = NULL, n = 500
)
#> Power analysis for DiD means (solved for minimum detectable effect)
#> n = 500 (per group), power = 0.800, effect = 2.5058
#> (treat = (50.000, 55.000), control = (50.000, 52.000), alpha = 0.05, deff = 1, var = (100.00, 100.00, 100.00, 100.00))
# Panel overlap reduces required n
power_did(
treat = c(0.50, 0.55), control = c(0.50, 0.48),
outcome = "prop", effect = 0.07, overlap = 0.5, overlap_cor = 0.6
)
#> Power analysis for DiD proportions (solved for sample size)
#> n = 1119 (per group), power = 0.800, effect = 0.0700
#> (treat = (0.500, 0.550), control = (0.500, 0.480), alpha = 0.05, deff = 1, overlap = 0.50, overlap_cor = 0.60)