Builds recipe-aware bootstrap replicate weights for two or more waves that are
coordinated by PSU: a PSU present in several waves gets the same resampling in
all of them, so the sampling covariance between waves – which the overlap of a
rotating panel induces – is captured. Feed the result to change_estimate() for the
honest variance of a net change. Ignoring the coordination (a separate per-wave
bootstrap) over-estimates the variance of change whenever the waves overlap and are
correlated.
Usage
wave_bootstrap(
specs,
replicates = 500L,
strata = NULL,
psu = NULL,
m = NULL,
seed = NULL,
refit_steps = "all",
resample = c("multinom", "binom"),
progress = TRUE
)Arguments
- specs
a named list of
weighting_specobjects, one per wave; the names are the wave labels used bychange_estimate().- replicates
number of bootstrap replicates.
- strata, psu
column names of the design strata and PSU, present in every wave's data. The PSU id must be consistent across waves (the same value = the same PSU): that consistency is what makes the coordination possible.
strata = NULLtreats the whole sample as one stratum;psu = NULLtreats each row as its own PSU.- m
optional PSU resample size per stratum (default
n_h - 1, the Rao-Wu choice).- seed
optional integer seed for the permanent uniforms (reproducibility).
- refit_steps
which recipe steps to re-run per replicate.
"all"(default, the honest recipe-aware bootstrap) re-preps the whole recipe, propagating the variance of every step."calibration"freezes everything up to the first calibration step and re-runs only calibration per replicate – the Statistics Canada LFS convention (the Rao-Wu factor is applied to the frozen pre-calibration subweight). A character vector of step classes (e.g.c("step_nonresponse", "step_calibrate")) splits at the first one matched: the prefix is frozen, the suffix re-prepped. The point estimate always uses the full recipe; only the replicate variance is affected.- resample
the Rao-Wu resample scheme.
"multinom"(default) draws an exact multinomial per stratum (counts sum tom_h), the centred Rao-Wu draw, which gives an unbiased replicate variance for composite/calibration estimators and for totals;"binom"(legacy) draws an independent binomial per PSU (counts need not sum tom_h), which loses the multinomial's negative between-PSU covariance and estimates an uncentred variance – only mildly high for a ratio or mean (~+8-10%) but a large overestimate for a total (up to an order of magnitude), so use"multinom"when estimating totals. Both share the per-PSU uniforms; the multinomial coordinates across rotating waves exactly when the PSU sets match (identical or disjoint waves) and approximately otherwise.- progress
show a progress message per wave.
Value
an object of class weightflow_wave_boot: per-wave point weights, replicate
matrices (aligned by replicate index across waves), the per-wave data, and the design.
Details
Self-contained: it does not modify bootstrap_weights(); each wave's recipe is
re-run through prep() on perturbed base weights, exactly as the single-sample
bootstrap does, but with a PSU-coordinated Rao-Wu draw shared across waves.
Composite (CRE) recursion is handled automatically: when a wave's recipe holds a
step_cre() whose previous is the preceding wave, that wave's estimated control
totals Zhat* are re-estimated per replicate from the previous wave's replicate-b
weights (not the frozen point weights), so the reported variance includes the
sampling variance of Zhat itself. Waves are processed in order and each wave's
replicate matrix is carried into the next, giving the full coordinated variance of
the recursive estimator. (Assumes each step_cre's previous is the immediately
preceding wave in specs; otherwise that step keeps its fixed point previous.)
Examples
t1 <- subset(panel_ine, ola == 1 & disp == "R")
t2 <- subset(panel_ine, ola == 2 & disp == "R")
wb <- wave_bootstrap(
list(T1 = weighting_spec(t1, base_weights = w_base),
T2 = weighting_spec(t2, base_weights = w_base)),
replicates = 200, strata = "estrato", psu = "psu", seed = 1, progress = FALSE)
change_estimate(wb, function(w, d) weighted.mean(d$desocupado, w, na.rm = TRUE))
#> <weightflow net change>
#> T1 -> T2
#> change : -0.0149512 SE 0.00944777
#> 95% CI : [-0.0334685, 0.00356605]
#> V1 0.0001239 | V2 0.0001211 | Cov 7.791e-05 | rho 0.636 (levels)
#> V = 8.926e-05 vs V1+V2 = 0.0002451 (deff_change 0.364: overlap saved 64%)
