Skip to main content
v2026.11,858 entries · CC-BY 4.0

Bootstrap in R: boot() and boot.ci() Step by Step

How to run a bootstrap in R with boot() and boot.ci(), including studentized intervals, log-scale intervals and parallel runs on Windows.

Written and maintained by CASRAI Editorial Board

Last updated

To run a bootstrap in R, write a function that takes the data and a vector of indices and returns your statistic, pass it to boot() from the boot package, then pass the result to boot.ci() for confidence intervals. The step most tutorials skip is the studentized interval: it only works if your statistic function also returns a variance estimate, and the manual’s warning about extreme order statistics tells you when the number of replicates is too small to trust an interval. Both are covered below, along with Windows parallelism and log-scale intervals.

This guide covers the software steps. For the idea behind resampling, see bootstrapping in statistics.

What it is used for in research

The boot package accompanies Davison and Hinkley’s book Bootstrap Methods and Their Application (1997). Researchers use it to put a confidence interval or a standard error on a statistic that has no convenient formula, such as a ratio of two means, a median, or a correlation. Related resampling tools sit on neighbouring pages: the jackknife leaves one observation out at a time, and permutation tests shuffle labels to test a null hypothesis rather than to estimate an interval. Bootstrap confidence intervals for an indirect effect are discussed in mediation analysis methods and reporting.

Install or access (official source only)

The boot package is published on CRAN (cran.r-project.org/web/packages/boot). CRAN lists version 1.3-32, published 2025-08-29, with priority Recommended, the tier of packages distributed alongside R itself. Load it with:

library(boot)

If R reports that there is no package called boot, install it from CRAN with install.packages("boot") and load it again.

Step-by-step: statistic function, boot(), boot.ci()

1. Write the statistic function

Per the package manual, the first argument passed to your statistic is always the original data, and the second is a vector of indices, frequencies or weights that defines the bootstrap sample. Which of the three you receive is set by stype: "i" for indices (the default), "f" for frequencies, "w" for weights. The manual states that the statistic is treated as a black box and is not checked, so test it yourself on the full sample first.

mean_fn <- function(d, i) {
  mean(d[i])
}
x <- mtcars$mpg
mean_fn(x, seq_along(x))   # must equal mean(x)

2. Call boot()

set.seed(2026)
b <- boot(data = x, statistic = mean_fn, R = 2000)
b

R is the number of bootstrap replicates. The default sim = "ordinary" resamples cases with replacement; the manual also lists "parametric", "balanced", "permutation" and "antithetic". The object stores .Random.seed as it was when the call started, so call set.seed() before boot() if you want to rerun the same replicates.

3. Call boot.ci()

boot.ci(b, conf = 0.95, type = c("norm", "basic", "perc", "bca"))

boot.ci() offers five equi-tailed two-sided nonparametric intervals through type: "norm" (first-order normal approximation), "basic", "stud" (studentized), "perc" (percentile) and "bca" (adjusted percentile). With type = "all", the default, it returns all five. Formulae are in Davison and Hinkley (1997), chapter 5.

4. A ratio statistic with weights

The manual’s own example bootstraps a ratio on the city data set that ships with boot, using weights instead of indices:

ratio <- function(d, w) sum(d$x * w) / sum(d$u * w)
city.boot <- boot(city, ratio, R = 999, stype = "w", sim = "ordinary")
boot.ci(city.boot, conf = c(0.90, 0.95),
        type = c("norm", "basic", "perc", "bca"))

5. Studentized intervals need a variance

The manual says variance estimates are required for studentized intervals. By default, with two values in t0, boot.ci() reads the second as the variance. So the statistic must return the estimate and its variance:

mean_var <- function(d, i) {
  v <- d[i]
  c(mean(v), var(v) / length(v))
}
bs <- boot(x, mean_var, R = 2000)
boot.ci(bs, type = c("perc", "stud"))   # index = 1:2 by default

6. Intervals on a transformed scale

For norm, stud and bca intervals you can compute on another scale with h, its derivative hdot, and the inverse hinv. The manual’s example uses the log scale: boot.ci(air.boot, type = c("norm","basic","perc","stud"), h = log, hdot = function(x) 1/x). If hinv is not given, the intervals are returned on the transformed scale.

7. Stratified and parallel runs

For two groups, pass strata so resampling happens within each group. To speed up large runs, set parallel and ncpus. "multicore" is not available on Windows; use "snow", and note the manual’s warning that with snow the statistic must set up its own environment through lexical scoping.

Output and how to read it

A boot object holds t0 (the statistic on the original data) and t (a matrix with one row per replicate), plus R, data, seed, statistic, sim, stype, call and strata. Printing it shows the original value, the bootstrap bias and the bootstrap standard error. Plot it with plot(b) to see the histogram and Q-Q plot of t.

In boot.ci() output, the normal interval has three columns (level, lower, upper). Every other interval has five: the level, two order-statistic indices, and the endpoints. Those two indices are positions in the sorted replicates, which is why they change when you change R. The normal interval also applies the bootstrap bias correction. Report which type you used, R, and the seed.

Troubleshooting

  • Studentized interval is missing or errors: the statistic returned only one value. Return the estimate and its variance, or supply var.t0 and var.t.
  • Warning about the smallest or largest order statistic: the manual says such intervals should not be considered reliable. Increase R and rerun.
  • BCa fails when extra arguments are used: BCa computes empirical influence values with empinf, which calls the statistic again, so pass the extra arguments through ....
  • Parallel code errors on Windows: "multicore" is unavailable there; use "snow".
  • Results change between runs: set the seed before boot(). The manual notes that reproducibility needs more care with simple = TRUE, parametric simulation, or a statistic that uses random numbers.
  • Memory use is high: simple = TRUE avoids the n-by-R index array, at the cost of speed.

Free alternatives

Tool Function What the documentation lists
R, boot package boot(), boot.ci() Five interval types: norm, basic, stud, perc, bca; parametric, balanced, permutation and antithetic simulation
Python, SciPy scipy.stats.bootstrap Two-sided bootstrap confidence interval; methods percentile, basic and BCa (default BCa); 9999 resamples by default

FAQ

Which bootstrap interval should I report?

The package documentation does not rank them; it provides five. Report the type you chose, the number of replicates and the seed, and check that the replicate distribution in plot(b) is not badly skewed before relying on the normal interval.

How many replicates (R) do I need?

The manual gives no fixed number. Its practical signal is the warning when an interval uses the smallest or largest of the R values; if you see it, raise R. Its own examples use R = 999.

What is the difference between stype “i”, “f” and “w”?

It sets what your statistic receives as its second argument: indices, frequencies or weights. The ratio example above uses weights.

Does clustered or dependent data change this?

Ordinary resampling treats rows as independent. For grouped data, see clustered standard errors before choosing what to resample. For modelling in R more broadly, see logistic regression in R.

Sources (official docs)

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Bootstrap in R: boot() and boot.ci() Step by Step

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.