# Finite-sample coverage of CR0, CR1 and wild-cluster-bootstrap-t intervals for a mean with few clusters Executable note: every number below is produced by `~/wp29/venv/bin/python out/analysis.py` (≈2 s), which writes `out/results.json`, `out/table1.csv` and `out/figure1.png` from `data/design.csv` only. Keys of `out/results.json` are cited in brackets. ## Question With N observations in G clusters (G ∈ {5, 10, 30}) and intra-cluster correlation ICC ∈ {0.0, 0.2, 0.5}, how close to 95% is the actual coverage of three cluster-robust intervals for the population mean μ (estimated by ȳ): CR0 with a normal critical value, CR1 with a t(G−1) critical value, and the unrestricted Rademacher wild cluster bootstrap-t (WCB)? We also estimate the relative bias E[V̂]/Var(ȳ) of the CR0/CR1 variance estimators, the Monte Carlo (MC) SE of each coverage, and the failure regimes (coverage < 0.90). ## Data and exclusions No observed data. The only input is `data/design.csv` (9 rows [`n_input_rows`], SHA-256 f4ff004e…; audit in `out/state/data_audit.md`): one row per cell with the cluster sizes (pattern 8, 16, 32, 64 repeated; N = 128, 264, 864), R = 2000 [`R`], B = 399 [`B`], and a per-cell seed (C1 seed 20261101 [`random_seed`]). All rows passed consistency checks (G sizes listed, sizes summing to N), so no cell was excluded (`out/exclusions.csv`: 9 → 9). 9 cells [`n_cells`] × 2000 replications = 18000 simulated samples [`n_analysed`]. The design issues found [`data_issues`]: (i) at G = 5 Rademacher weights have only 32 distinct vectors (16 distinct |t*| values), so the WCB critical value is coarse; (ii) at ICC = 0 the cluster effect is degenerate (zero variance). Neither changed the procedures. Feasibility: complete [`feasibility`]. ## Method DGP per replication: y_ig = μ + u_g + e_ig, u_g ~ N(0, ICC), e_ig ~ N(0, 1−ICC), μ = 0. Exact Var(ȳ) = [ICC·Σn_g² + (1−ICC)N]/N². For each cell, `numpy.random.default_rng(seed)`; per replication draws in the order u (G), e (N), Rademacher weight matrix (B × G). - CR0: V̂ = Σ_g(Σ_i ê_ig)²/N², interval ȳ ± 1.96√V̂. - CR1: V̂_CR1 = G/(G−1)·V̂_CR0, interval ȳ ± t_{0.975,G−1}√V̂_CR1. - WCB: y* = ȳ + w_g ê_ig, t*_b = (ȳ* − ȳ)/√V̂*_CR1 (V̂* recomputed on the bootstrap sample), q = 0.95 empirical quantile of |t*|, interval ȳ ± q√V̂_CR1. Vectorised via cluster residual sums; checked against a brute-force construction of y* (max difference 1e-14). Empirical-quantile convention: the ⌈(B+1)·0.95⌉ = 380th order statistic of the 399 |t*| values (the standard convention for B = 399); the numpy linear-interpolation quantile is reported as a sensitivity [`sensitivity_wcb_coverage_numpy_quantile`]. - Coverage = share of R intervals containing μ; MC SE = √(p̂(1−p̂)/R); relative bias = mean(V̂)/exact Var(ȳ), with MC SE sd(V̂)/(√R·Var(ȳ)) [`mc_se_rel_bias_var`]. - Baseline (P2): the naive i.i.d. interval ȳ ± 1.96·s/√N that ignores clustering [`baseline_iid_coverage`]. ## Results Full table: `out/table1.csv`; figure: `out/figure1.png` (coverage vs G, one panel per ICC, ±1.96 MC SE bars, lines at 0.95 and 0.90). Coverage [`coverage`] (MC SE ≈ 0.005–0.010 [`mc_se_coverage`]): | G | ICC | CR0 | CR1 | WCB | naive iid baseline | |---|---|---|---|---|---| | 5 | 0.0 | 0.781 | 0.912 | 0.858 | 0.941 | | 5 | 0.2 | 0.721 | 0.885 | 0.855 | 0.460 | | 5 | 0.5 | 0.717 | 0.876 | 0.851 | 0.287 | | 10 | 0.0 | 0.897 | 0.944 | 0.938 | 0.957 | | 10 | 0.2 | 0.857 | 0.916 | 0.933 | 0.488 | | 10 | 0.5 | 0.853 | 0.907 | 0.935 | 0.313 | | 30 | 0.0 | 0.928 | 0.940 | 0.945 | 0.952 | | 30 | 0.2 | 0.921 | 0.935 | 0.947 | 0.485 | | 30 | 0.5 | 0.917 | 0.930 | 0.944 | 0.299 | 1. **Baseline.** Ignoring clustering gives near-nominal coverage only at ICC = 0 and coverage of 0.29–0.49 when ICC > 0 [`baseline_iid_coverage`]; all three cluster-robust intervals do much better whenever ICC > 0. 2. **Failure regimes.** 11 of 27 pairs have coverage < 0.90 [`n_failure_cells`, `failure_cells`]: CR0 at G = 5 and G = 10 (all ICC; 0.717–0.897), CR1 at G = 5 with ICC = 0.2 and 0.5 (0.885, 0.876), and WCB at G = 5 (all ICC; 0.851–0.858). No pair fails at G = 30. 3. **Variance bias.** CR0 underestimates Var(ȳ) strongly with few clusters: E[V̂]/Var(ȳ) = 0.48–0.66 at G = 5, 0.76–0.86 at G = 10, 0.93–0.94 at G = 30 [`rel_bias_var`]. The G/(G−1) factor of CR1 reduces but does not remove the bias at G = 5 (0.60–0.83); at G = 30 CR1 is within 0.96–0.98. The downward bias is larger with ICC > 0, plausibly because the unequal cluster sizes make the large cluster (n = 64) carry much of the variance and its residual sum is shrunk most by centring on ȳ. 4. **Comparison of procedures.** At G = 5, CR1 has the highest average coverage (0.8905 vs WCB 0.854 and CR0 0.740) [`best_procedure_small_G`, `mean_coverage_G5`]. At G = 10 and 30 with ICC > 0, WCB is closest to nominal (0.933–0.947). WCB intervals at G = 5 are much wider on average than CR1 (`mean_ci_halfwidth` in table1.csv, e.g. 1.39 vs 0.79 at ICC = 0.5) yet cover less often, which points to an unstable, data-dependent critical value when only 16 distinct |t*| values exist. 5. **Consistent with nominal** (|p̂ − 0.95| ≤ 2 MC SE): only 5 of 27 pairs [`nominal_cells`]: CR1 at (G=10, ICC=0) and (G=30, ICC=0), and WCB at G = 30 for every ICC. CR0 is never consistent with nominal, not even at G = 30. ## Uncertainty Each coverage estimate is a binomial proportion with R = 2000; its MC SE [`mc_se_coverage`] ranges from about 0.005 (coverage near 0.95) to 0.010 (coverage near 0.72), so a 95% MC interval is about ±0.01–0.02. Pairs near the 0.90 threshold are therefore classified with limited confidence: CR0 at (G=10, ICC=0) = 0.8965 (SE 0.0068), CR1 at (G=5, ICC=0) = 0.9115 (SE 0.0064) and CR1 at (G=5, ICC=0.2) = 0.8845 (SE 0.0071) all lie within 2 MC SE of 0.90, so their failure/non-failure label could flip with another seed. The "nominal-consistent" label is a 2-SE screen applied to 27 pairs without multiplicity adjustment, so it is not a formal test. Classifications far from the boundaries (CR0 at G = 5, WCB at G = 5, everything at G = 30 vs 0.90) are robust. The relative-bias estimates have MC SEs of 0.007–0.016 [`mc_se_rel_bias_var`]. As a check, the MC relative bias of CR0 was compared with its exact analytic expectation (verification script in `out/state/verify/`): |z| ≤ 1.4 in 8 of 9 cells and z = 2.46 in C2 (G=5, ICC=0.2: MC 0.531 vs exact 0.500), a deviation that fits the somewhat large realised variance of ȳ in that cell; the conclusions about bias do not depend on it. The WCB critical value carries its own bootstrap noise (B = 399), which is part of the procedure's coverage. Switching to numpy's interpolated quantile changes WCB coverage by at most 0.003 and leaves the failure set unchanged [`sensitivity_wcb_coverage_numpy_quantile`]. Seeds are fixed, so re-running gives identical numbers; a different seed would give MC variation of the size of these SEs. ## Limitations and open issues - **Distributions:** only Gaussian cluster effects and errors. Skewed or heavy-tailed u_g/e_ig, which usually hurt few-cluster inference more, are not covered. - **Heterogeneity:** only one fixed unequal size pattern (8/16/32/64) and homoskedastic, equal ICC across clusters. Cluster-size-dependent effects, heteroskedasticity across clusters and informative cluster sizes are not studied. Results may depend on the size pattern (e.g. the dominant 64-observation cluster at G = 5). - **Regressors:** only the mean (intercept-only model) is studied. Regression slopes, leverage from treated clusters and few treated clusters are outside the design. - **Other weights / variants:** only Rademacher weights with the unrestricted (non-null-imposed) WCB-t were studied. Webb six-point or Mammen weights, the restricted WCR bootstrap, full enumeration of the 32 sign vectors at G = 5, CR2/CR3 (bias-reduced linearisation) and Satterthwaite/Bell–McCaffrey degrees of freedom were not evaluated. The G = 5 WCB results should not be generalised to those variants. - The grid covers only G ∈ {5, 10, 30} and ICC ∈ {0, 0.2, 0.5}; the transition between G = 10 and 30 is not resolved. - Interval length was summarised only by the mean half-width; the WCB half-width distribution at G = 5 (which seems heavy-tailed) was not analysed further.