bootstrapx
Production-grade bootstrap uncertainty estimation for Python.
16 bootstrap methods · sklearn-compatible · pandas accessor · memory-safe batching
Why bootstrapx?
scipy.stats.bootstrap covers 3 CI types and only iid data.
The R boot package is comprehensive but not Pythonic.
bootstrapx bridges this gap.
| Feature | scipy |
arch |
bootstrapx |
|---|---|---|---|
| BCa interval | ✅ | ❌ | ✅ |
| Studentized (bootstrap-t) | ❌ | ❌ | ✅ |
| Bayesian bootstrap | ❌ | ❌ | ✅ |
| Poisson weights / Bernoulli subsets | ❌ | ❌ | ✅ |
| MBB / CBB / Stationary block | ❌ | ✅ | ✅ |
| Sieve (AR-based) | ❌ | ❌ | ✅ |
| Wild bootstrap | ❌ | ✅ | ✅ |
| Cluster / Stratified | ❌ | ❌ | ✅ |
| scikit-learn CV API | ❌ | ❌ | ✅ |
pandas .bootstrap accessor |
❌ | ❌ | ✅ |
| Reproducible (seeded RNG) | ✅ | partial | ✅ |
| Constant memory (batched) | ❌ | ❌ | ✅ |
Installation
pip install bootstrapx-lib # core (numpy + scipy only)
pip install "bootstrapx-lib[pandas]" # + pandas accessor
pip install "bootstrapx-lib[sklearn]" # + scikit-learn CV integration
pip install "bootstrapx-lib[pandas,sklearn]" # all integrations
Quick Start
Basic usage
import numpy as np
from bootstrapx import bootstrap
data = np.random.default_rng(42).normal(5, 2, size=300)
result = bootstrap(data, np.mean)
print(result)
# BootstrapResult(method='bca', theta_hat=4.97, se=0.11, CI=[4.75, 5.19])
print(result.confidence_interval.low, result.confidence_interval.high)
print(5.0 in result.confidence_interval) # True
pandas accessor
import pandas as pd
import numpy as np
import bootstrapx # registers .bootstrap accessor
s = pd.Series(np.random.default_rng(0).exponential(scale=2, size=500))
# On a Series
r = s.bootstrap.bca(np.mean)
print(r)
# On a DataFrame — column-wise summary
df = pd.DataFrame({"control": s, "treatment": s * 1.1 + 0.3})
print(df.bootstrap.summary(np.mean))
# theta_hat ci_low ci_high se method
# column
# control 1.9973 1.8215 2.1862 0.0941 bca
# treatment 2.4970 2.3036 2.7048 0.1035 bca
scikit-learn cross-validation
from bootstrapx import BootstrapCV
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_breast_cancer
X, y = load_breast_cancer(return_X_y=True)
cv = BootstrapCV(n_splits=200, random_state=42)
scores = cross_val_score(
GradientBoostingClassifier(n_estimators=100),
X, y, cv=cv, scoring="roc_auc"
)
print(f"AUC: {scores.mean():.4f} ± {scores.std():.4f}")
# AUC: 0.9921 ± 0.0071
Time-series bootstrap
import numpy as np
from bootstrapx import bootstrap
rng = np.random.default_rng(0)
y = np.zeros(500)
for t in range(1, 500):
y[t] = 0.7 * y[t-1] + rng.normal()
# Moving Block Bootstrap — preserves serial correlation
result = bootstrap(y, np.mean, method="mbb", block_length=15, n_resamples=4999)
print(result)
# Sieve Bootstrap — fits AR(p) model to residuals
result = bootstrap(y, np.mean, method="sieve", n_resamples=9999)
print(result)
A/B test with clustered data
import numpy as np
from bootstrapx import bootstrap
n_clusters = 50
cluster_ids = np.repeat(np.arange(n_clusters), 20)
rng = np.random.default_rng(1)
data = rng.normal(loc=cluster_ids * 0.1, scale=1.0)
result = bootstrap(
data, np.mean,
method="cluster",
cluster_ids=cluster_ids,
n_resamples=4999,
)
print(result)
# Correctly wider CI that accounts for within-cluster correlation
Bayesian bootstrap with a custom statistic
Bayesian bootstrap evaluates a functional directly under Dirichlet weights.
np.mean, np.nanmean, and np.average work without extra configuration.
For a custom statistic, provide its weighted form explicitly:
def second_moment(x):
return np.mean(x**2)
def weighted_second_moment(x, weights):
return np.sum(weights * x**2)
result = bootstrap(
data,
second_moment,
method="bayesian",
weighted_statistic=weighted_second_moment,
random_state=42,
)
Performance
Measured on Apple M1, Python 3.12, n_resamples=4 999, median of 5 runs.
Run yourself: python benchmarks/bench_speed.py --quick
BCa (bias-corrected and accelerated):
| n | scipy (ms) | bootstrapx (ms) | Speedup |
|---|---|---|---|
| 200 | 9.6 | 5.8 | 1.7× |
| 2 000 | 69 | 58 | 1.2× |
| 5 000 | 433 | 156 | 2.8× |
| 10 000 | 1 015 | 289 | 3.5× |
At n < 1 000, scipy and bootstrapx are comparable; bootstrapx applies a vectorised fast path for numpy built-ins (mean, median, std, etc.) at n < 500. Speedup grows with sample size due to O(n) vectorised jackknife vs O(n²) in scipy.
Coverage accuracy
BCa empirical coverage at nominal 95%, 1 000 Monte Carlo simulations across normal, log-normal, exponential and t(3) distributions: bootstrapx matches scipy to within simulation noise (< 0.01) for mean and median.
Note: BCa coverage for
np.stdon heavy-tailed distributions (exponential) is ~91–93% at n = 200 — identical behaviour in both bootstrapx and scipy. This reflects known instability of jackknife acceleration for scale statistics, not a library-specific issue. Usen_resamples ≥ 9 999ormethod="studentized"for better coverage when estimating variance.
Run yourself: python benchmarks/bench_coverage_accuracy.py --fast
Documentation
📖 Full docs: artyerokhin.github.io/bootstrapx
All supported methods
| Method | method= |
Use case |
|---|---|---|
| BCa | "bca" |
General purpose, best coverage accuracy |
| Percentile | "percentile" |
Simple, fast |
| Basic (Hall) | "basic" |
Symmetric distributions |
| Studentized | "studentized" |
Known variance structure |
| Bayesian | "bayesian" |
Bayesian UQ, non-parametric posterior |
| Poisson weights | "poisson" |
Weighted bootstrap, survey data |
| Bernoulli subsets | "bernoulli" |
Calibrated random-subset inference |
| Subsampling | "subsampling" |
Root-scaled inference from smaller samples |
| Moving Block (MBB) | "mbb" |
Stationary time series |
| Circular Block (CBB) | "cbb" |
Stationary TS, edge-effect free |
| Stationary | "stationary" |
Politis & Romano (1994) |
| Tapered Block | "tapered" |
Paparoditis & Politis (2001) |
| Sieve | "sieve" |
AR(p) time series (Bühlmann 1997) |
| Wild | "wild" |
Heteroscedastic residuals (Wu 1986) |
| Cluster | "cluster" |
Multi-level / panel data |
| Stratified | "strata" |
Stratified sampling designs |
Contributing
git clone https://github.com/artyerokhin/bootstrapx.git
cd bootstrapx
pip install -e ".[dev,pandas]"
pytest tests/ -v
Citation
If you use bootstrapx in academic work:
@software{bootstrapx,
author = {Erokhin, Artem},
title = {bootstrapx: Production-grade bootstrap uncertainty estimation},
url = {https://github.com/artyerokhin/bootstrapx},
version = {0.4.2},
year = {2026},
}
License
MIT — see LICENSE.
Release files for bootstrapx-lib 0.4.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bootstrapx_lib-0.4.2.tar.gz | 33.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bootstrapx_lib-0.4.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 59.8 kB
Release files / bootstrapx_lib-0.4.2.tar.gz
| Download URL | bootstrapx_lib-0.4.2.tar.gz |
|---|---|
| Size | 33.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
54f30e06f8d81a36e393ab84e9d3f41fcd7711f3624c33ad5b3b9a7a873f8d99
|
|
BLAKE2b-256 checksum How to use checksums |
8c4b20eb56cb03dcdde80eaff372e7c0848e6ad85e3d393996f30a85f82f1ab1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.
Transparency logRelease files / bootstrapx_lib-0.4.2-py3-none-any.whl
| Download URL | bootstrapx_lib-0.4.2-py3-none-any.whl |
|---|---|
| Size | 26.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c75a41cce0f1b2d39792989655afaf4b81d9b68f082ec9e94d804d15a1578ca5
|
|
BLAKE2b-256 checksum How to use checksums |
386dc3695f55ac53dad0a8ce0b116b71994b46d642b45ddcd68f64dde4a196eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 13, 2026.
Transparency log