Rubin pooling — algorithm as implemented¶
Implementation: src/longmi/pooling/rubin.py. Theory and citations: Proposition 3 of mathematical_foundations.md (Rubin 1987; Barnard & Rubin 1999).
Inputs¶
\(M \ge 2\) completed-data fits, each an AnalysisEstimate with
- parameter names, in identical order across fits (a permuted ordering raises; it is never silently realigned);
- point estimates \(\widehat Q^{(m)} \in \mathbb{R}^p\);
- complete-data covariance \(U^{(m)} \in \mathbb{R}^{p \times p}\) (validated symmetric with nonnegative diagonal);
- a common complete-data degrees of freedom \(\nu_{\mathrm{com}}\), or
Nonefor the large-sample reference.
Formulas¶
Per-parameter quantities use the diagonals (\(j = 1, \dots, p\)), matching
mice::pool.scalar (rule "rubin1987"):
- relative increase in variance: \(r_j = (1 + 1/M)\, B_{jj} / \overline U_{jj}\);
- proportion of total variance due to missingness: \(\lambda_j = (1 + 1/M)\, B_{jj} / T_{jj}\);
- Rubin (1987) large-sample degrees of freedom: \(\nu_{\mathrm{old},j} = (M - 1) / \lambda_j^2\) (infinite when \(\lambda_j = 0\));
- Barnard–Rubin (1999) small-sample adjustment, applied when \(\nu_{\mathrm{com}}\) is finite:
- fraction of missing information: \(\gamma_j = \dfrac{r_j + 2/(\nu_j + 3)}{1 + r_j}\) (with \(2/(\nu_j+3) \to 0\) when \(\nu_j = \infty\));
- confidence intervals: \(\overline Q_j \pm t_{\nu_j,\,1-\alpha/2}\sqrt{T_{jj}}\), with the normal reference when \(\nu_j = \infty\).
Degrees-of-freedom methods¶
pool_rubin(..., df_method=...) selects the rule; the point estimate and
\(T\) are identical across methods.
"barnard_rubin"(default) — Barnard–Rubin (1999), computed with the same algebraic rearrangement currentmice::pool.scalar(rule"rubin1987", mice ≥ 3.x) uses,
$$ \nu_j = \frac{(M-1)\,\omega_j} {(\nu_{\mathrm{com}}+3)(M-1) + \lambda_j^2\,\omega_j}, \qquad \omega_j = (1-\lambda_j)(1+\nu_{\mathrm{com}})\,\nu_{\mathrm{com}}, $$
which is well-defined at \(\lambda_j = 0\): with infinite
\(\nu_{\mathrm{com}}\), \(B_{jj} = 0\) gives \(\nu_j = \infty\) (normal
reference) and \(\gamma_j = 0\); with finite \(\nu_{\mathrm{com}}\) it gives
the observed-data df \(\nu_{\mathrm{obs},j}\). (Historical note: mice
versions predating this rearrangement clamped \(\lambda < 10^{-4}\);
current mice and longmi do not.)
- "large_sample" — Rubin (1987) \(\nu_j = (M-1)/\lambda_j^2\) even when
\(\nu_{\mathrm{com}}\) is provided (no Barnard–Rubin adjustment).
Edge cases¶
- \(B_{jj} = 0\): \(r_j = \lambda_j = 0\), \(T_{jj} = \overline U_{jj}\); df and
fmi per
df_methodabove. - \(M = 1\): refused — between-imputation variance is undefined.
- Non-positive \(\overline U_{jj}\): refused.
- Inconsistent
dfcomacross fits: refused. - The result is invariant to the order of the estimates list.
Cross-language parity¶
The default method matches mice::pool.scalar exactly, verified at
relative tolerance \(10^{-12}\) — including a \(\lambda < 10^{-4}\) clamp case
and a zero-\(B\) case
(validation/r/rubin_reference.R,
tests/cross_language/).