blinklinmult.compare.bootstrap¶
The paired cluster bootstrap, and the refusal to report one when it cannot.
The estimator is ordinary; the two decisions around it are what matter.
Resampling is paired. One draw of clusters is scored by every model, so the
difference between two models is computed within a draw rather than between two
independent draws. See resample().
Below :data:`MIN_CLUSTERS_FOR_INTERVAL` clusters, no interval is returned at all. This is deliberate and is the module’s sharpest opinion. A percentile bootstrap over one cluster resamples that same cluster every time: the spread is exactly zero and the “interval” has zero width, which reads as a precise estimate when it is the opposite. TalkingFace (one recording, 524 windows, 61 events) is the case this exists for. The alternative – silently falling back to window-level resampling to manufacture a number – is the error this whole package was written to avoid.
Attributes¶
Fewest clusters that can carry a confidence interval. |
|
Bootstrap replicates. |
|
Seed for the resampling draw, recorded alongside every result. |
Classes¶
A point estimate, with an interval when the data can carry one. |
Functions¶
|
Resample clusters and summarise a statistic over the draws. |
|
Bootstrap p-value for the null that the difference is zero. |
Module Contents¶
- blinklinmult.compare.bootstrap.MIN_CLUSTERS_FOR_INTERVAL = 10¶
Fewest clusters that can carry a confidence interval.
Below this the resampling distribution is too coarse for its tails to mean anything: with
nclusters a resample can only takendistinct values per slot, and the 2.5th percentile is estimated from a handful of distinct compositions. Ten is a judgement, not a theorem – it admits RN15 (20) and RN30 (35) while excluding TalkingFace (1) and MRL (6 subjects).
- blinklinmult.compare.bootstrap.DEFAULT_ROUNDS = 10000¶
Bootstrap replicates.
Large enough that the 2.5%/97.5% endpoints rest on ~250 replicates each, so the Monte Carlo noise on an endpoint is small next to the sampling noise the interval is reporting. Cheap here because a replicate is array arithmetic over precomputed per-recording scores, never a re-run of a model.
- blinklinmult.compare.bootstrap.DEFAULT_SEED = 20260905¶
Seed for the resampling draw, recorded alongside every result.
- class blinklinmult.compare.bootstrap.Interval[source]¶
A point estimate, with an interval when the data can carry one.
- Parameters:
point (float) – The statistic on the observed sample.
low (float | None) – Lower bound, or
Nonewhen refused.high (float | None) – Upper bound, or
Nonewhen refused.n_clusters (int) – Independent units behind the estimate. The honest sample size, which is why it travels with the number.
rounds (int) – Replicates drawn.
seed (int) – Seed used.
reason (str) – Why no interval was produced; empty when there is one.
- property reportable: bool¶
Whether an interval was produced.
- Returns:
Truewhen both bounds are present.- Return type:
bool
- property excludes_zero: bool¶
Whether the interval lies wholly above or below zero.
- Returns:
Falsewhen there is no interval, so an unreportable result is never mistaken for a significant one.- Return type:
bool
- blinklinmult.compare.bootstrap.bootstrap_statistic(statistic: collections.abc.Callable[[collections.abc.Sequence[int]], float], n_clusters: int, rounds: int = DEFAULT_ROUNDS, seed: int = DEFAULT_SEED) tuple[Interval, numpy.ndarray][source]¶
Resample clusters and summarise a statistic over the draws.
- Parameters:
statistic (Callable[[Sequence[int]], float]) – Maps cluster indices to a scalar. Called once per replicate, so it should be arithmetic over precomputed per-cluster values rather than anything that re-scores.
n_clusters (int) – Clusters available.
rounds (int) – Replicates.
seed (int) – Seed.
- Returns:
The summary, and the raw draws for a downstream p-value.
- Return type:
tuple[Interval, np.ndarray]
- blinklinmult.compare.bootstrap.two_sided_p(draws: numpy.ndarray) float[source]¶
Bootstrap p-value for the null that the difference is zero.
Uses the
(1 + count) / (B + 1)form rather than a bare proportion. The correction matters: without it a difference that never changes sign reportsp = 0, claiming certainty no finite resampling can support. With it the floor is2 / (B + 1), which is exactly whatBreplicates can evidence – and that identity is whattests/compare/test_bootstrap.pypins.- Parameters:
draws (np.ndarray) – Bootstrap distribution of the difference.
- Returns:
Two-sided p-value in
(0, 1].- Return type:
float