Finite-sample coverage of CR0, CR1 and wild-cluster-bootstrap-t intervals for a mean with few clusters
All numbers below are produced by out/analysis.py (run: ~/wp29/venv/bin/python out/analysis.py, ≈2 s) and are cited by their key in out/results.json. Full per-cell values are in out/table1.csv; the figure is out/figure1.png.
Question
When N observations are grouped in few (G = 5, 10, 30) unbalanced clusters with intra-cluster correlation ICC ∈ {0, 0.2, 0.5}, what is the actual coverage of three nominal-95% cluster-robust intervals for the mean μ (CR0 with z critical value; CR1 with t_{G−1}; unrestricted Rademacher wild cluster bootstrap-t, WCB), how biased are the CR0/CR1 variance estimators relative to the exact Var(ȳ), and in which (procedure, cell) pairs does coverage fall below 0.90?
Data and exclusions
No observed data. The only input is data/design.csv (n_input_rows: 9 rows; SHA-256 recorded in out/state/data_audit.md): 9 cells, cluster sizes 8,16,32,64 repeated (N = 128, 264, 864), R = 2000 (R), B = 399 (B), one seed per cell (C1 seed = random_seed; all seeds in seeds_by_cell). The audit found no missing values, duplicates or inconsistencies (sizes count = G, sum = N). No exclusions: all n_cells = 9 cells × 2000 replications = n_analysed = 18000 replications were simulated and analysed (out/exclusions.csv, one no-op step). feasibility = "complete". One design feature is recorded in data_issues: at G = 5 Rademacher weights take only 32 distinct values (16 distinct |t*|), so the bootstrap critical value is coarse; kept as specified. No bootstrap draw had a non-positive variance (n_degenerate_bootstrap_draws = 0).
Method
Per replication (numpy default_rng(cell seed), draws in fixed order u, e, W): y_ig = μ + u_g + e_ig, u_g ~ N(0, ICC), e_ig ~ N(0, 1−ICC), μ = 0. With ê = y − ȳ and S_g = Σ_i ê_ig: V̂_CR0 = Σ S_g²/N², CI ȳ ± 1.96√V̂_CR0; V̂_CR1 = G/(G−1)·V̂_CR0, CI ȳ ± t_{0.975,G−1}√V̂_CR1; WCB: B×G Rademacher matrix W, ȳ*−ȳ = Σ_g w_g S_g/N, bootstrap cluster residual sums w_g S_g − n_g(ȳ*−ȳ), V̂*_CR1 from these, t*_b = (ȳ*−ȳ)/√V̂*_CR1, q = 0.95 quantile of |t*| (numpy linear interpolation, wcb_quantile_method), CI ȳ ± q√V̂_CR1. Coverage = share of R intervals containing μ; MC SE = √(p̂(1−p̂)/R); relative bias = mean(V̂)/Var(ȳ) with Var(ȳ) = [ICC Σn_g² + (1−ICC)N]/N². Failure regime: coverage < 0.90; nominal-consistent: |p̂ − 0.95| ≤ 2 MC SE. Baseline (P2): the naive i.i.d. interval ȳ ± 1.96·s/√N on the same draws (baseline_iid_coverage).
Verification (out/state/checks.md): byte-identical re-run; vectorised WCB matches a brute-force construction of y* (diff 7e-15); MC relative bias of CR0 matches the closed-form E[V̂_CR0]/Var(ȳ) within 2 MC SE in 8/9 cells (z = +2.46 in G5_icc0.2); MC Var(ȳ)/exact in [0.93, 1.06] (check_mc_var_ybar_over_exact).
Results
Coverage (coverage, MC SE in mc_se_coverage):
| G | ICC | CR0 | CR1 | WCB | naive i.i.d. baseline |
|---|---|---|---|---|---|
| 5 | 0.0 | 0.781 | 0.912 | 0.855 | 0.941 |
| 5 | 0.2 | 0.721 | 0.885 | 0.854 | 0.460 |
| 5 | 0.5 | 0.717 | 0.876 | 0.849 | 0.287 |
| 10 | 0.0 | 0.897 | 0.944 | 0.936 | 0.957 |
| 10 | 0.2 | 0.857 | 0.916 | 0.930 | 0.488 |
| 10 | 0.5 | 0.853 | 0.907 | 0.933 | 0.313 |
| 30 | 0.0 | 0.928 | 0.940 | 0.943 | 0.952 |
| 30 | 0.2 | 0.921 | 0.935 | 0.946 | 0.485 |
| 30 | 0.5 | 0.917 | 0.930 | 0.943 | 0.299 |
- Failure regimes (
failure_cells,n_failure_cells= 11): CR0 at every G = 5 and G = 10 cell (6 pairs); WCB at all three G = 5 cells; CR1 at G = 5 with ICC = 0.2 and 0.5. No procedure fails at G = 30. - Nominal-consistent pairs (
nominal_cells, 5 pairs): cr1_G10_icc0.0, cr1_G30_icc0.0, wcb_G30_icc0.0, wcb_G30_icc0.2, wcb_G30_icc0.5. CR0 is never consistent with 0.95, even at G = 30 (0.917–0.928). - Best at G = 5 (
best_procedure_small_G= "cr1"): average G = 5 coverage 0.891 for CR1, 0.853 for WCB, 0.740 for CR0 (avg_coverage_G5). The CR1 − WCB difference is 0.038 with paired MC SE 0.0035 (avg_coverage_G5_paired_diff), so the ranking is not a Monte Carlo artefact. At G = 10 with ICC > 0, WCB covers better than CR1 (0.930/0.933 vs 0.916/0.907). - Variance bias (
rel_bias_var): both sandwich estimators are biased downward, most at small G and high ICC. CR0: 0.66, 0.53, 0.48 at G = 5 (ICC 0, 0.2, 0.5); 0.86, 0.76, 0.77 at G = 10; 0.94, 0.93, 0.93 at G = 30. CR1: 0.83, 0.66, 0.60 at G = 5; 0.95, 0.85, 0.86 at G = 10; 0.98, 0.96, 0.96 at G = 30. The unbalanced sizes (one 64-observation cluster dominates) make the bias much worse than the balanced-cluster factor (G−1)/G. - Baseline: the naive i.i.d. interval is fine at ICC = 0 but covers only 0.29–0.49 when ICC > 0 (
baseline_iid_coverage), whatever G is. All three cluster-robust procedures improve on it there. - Mean CI half-widths are in
table1.csv(mean_ci_halfwidth). At G = 5 the WCB interval is on average wider than CR1 but still covers less. One plausible explanation (not tested here) is that q varies a lot across replications, because the bootstrap distribution has only 16 distinct |t*| values.
Uncertainty
Each coverage is a binomial proportion over R = 2000 independent replications. Its MC SE (mc_se_coverage) is 0.005–0.010, so a 95% MC interval is about ±0.010–0.020. The figure shows ±1.96 MC SE bars. Classifications near the 0.90 threshold are therefore fragile. cr1_G5_icc0.0 (0.912), cr0_G10_icc0.0 (0.897) and cr1_G10_icc0.5 (0.907) are within 2 MC SE of 0.90 (cells_within_2se_of_failure_line); a different seed could move them across the line. The "nominal-consistent" label is a 2-SE screen, not a test with multiplicity control: across 27 pairs, some misclassification is expected. With R = 2000 we cannot resolve coverage differences much smaller than ≈0.02. The relative-bias estimates have MC SE 0.007–0.016 (mc_se_rel_bias_var). Because V̂ is right-skewed at small G, the normal approximation behind that SE is rough, which matches the one 2.46-SE discrepancy from the exact value in G5_icc0.2. The paired SE for the G = 5 ranking uses the fact that all procedures are evaluated on the same replications. The bootstrap critical value adds its own simulation noise (B = 399), and that noise is included in the WCB coverage estimate.
Limitations and open issues
- Distributions: only Gaussian random effects and errors are covered. Skewed or heavy-tailed u_g/e_ig, which are known to matter for few-cluster inference, are not.
- Heterogeneity: the design has a homoskedastic random intercept and a single fixed size pattern (8,16,32,64). It does not cover heteroskedasticity across clusters, cluster-size–outcome correlation, or other degrees of imbalance. Results may depend strongly on the dominant 64-observation cluster.
- Regressors: only the mean (intercept-only model) is studied. Regression slopes, leverage and fixed effects are not covered.
- Other weights / variants: only Rademacher weights, the unrestricted (non-null-imposed) WCB-t, and the symmetric percentile-t interval with numpy's linear-interpolation quantile are studied. Webb 6-point weights, restricted WCB (WCR), enumeration of all 2^G weight vectors at G = 5, CR2/CR3 (bias-reduced) estimators, and other degrees-of-freedom corrections are not evaluated. Results for the WCB at G = 5 are specific to these choices.
- G ∈ {5, 10, 30} only; the location of the transition between 10 and 30 is not resolved.
- The single 2.46-SE deviation between the MC and exact CR0 bias (G5_icc0.2) is reported, not removed. We read it as MC noise in a skewed estimator (see
out/state/checks.md).