Answer
Why does bootstrapping work? A plain-language explanation
The short answer
Your sample is the best picture you have of the population. The bootstrap treats that picture as a stand-in population and redraws samples from it, with replacement, to see how much a statistic wobbles from sample to sample. It does not create new information; it measures uncertainty. It works well when the sample is a fair, reasonably sized snapshot of the population, and poorly when it is not.
The problem the bootstrap solves
Any number you calculate from a sample, such as a mean, a median or a correlation, would have come out a little differently if you had happened to draw a different sample. To judge how much to trust it, you want to know how much it would vary across all the samples you could have drawn. That spread is the standard error, and it is the basis of every confidence interval.
The ideal way to find it would be to go back to the population, collect hundreds of new samples, and watch the statistic bounce around. You cannot do that: you have one sample, and collecting more costs time and money. For a few statistics, like the mean, a formula gives the answer. For many others, like a median, a ratio or a trimmed mean, there is no simple formula.
The key idea: let the sample stand in for the population
Here is the explanation you can give a neighbor. Imagine you want to know about the jelly beans in a huge warehouse, but you only have a jar of 40 that were scooped out at random. If the scoop was fair, the jar looks like a miniature version of the warehouse: roughly the same share of red, green and black beans.
So pretend the jar is the warehouse. Make a big pile out of many copies of your jar, and scoop 40 beans from it again and again. Each scoop is a plausible sample you might have gotten. Watching how the share of red beans varies between these scoops tells you how much it would vary between real scoops from the warehouse. Drawing from many copies of the jar is exactly what sampling with replacement does: after you pick a bean, you put it back, so it can be picked again.
The leap that feels suspicious is this: we are not learning about the population's center from the resamples. The center still comes from the original sample. What the resamples teach us is the size of the wobble, and the wobble depends mainly on the shape and spread of the data and on the sample size, which a decent sample captures well.
Statisticians call this the plug-in principle: whenever a calculation needs the unknown population, plug in the sample instead. Bradley Efron introduced the method in 1979, and the name comes from the phrase about pulling yourself up by your own bootstraps.
See it in R and Python
Because the example below simulates the population, we can do the impossible and compare the bootstrap against the truth. It draws one sample of 40 skewed waiting times (true mean 10), then estimates the standard error of the mean in three ways: by drawing 10,000 fresh samples from the population, by bootstrapping the one sample, and by the usual formula. Finally it repeats the whole study 1,000 times to check how often a 95% bootstrap interval captures the true mean. Both versions use only base tools.
R
set.seed(26088)
# A skewed "population" we normally never get to see: waiting times, mean 10
pop_mean <- 10
n <- 40
# The one sample we actually have
x <- rexp(n, rate = 1 / pop_mean)
round(mean(x), 2)
# God's-eye view: draw 10,000 fresh samples from the population
fresh_means <- replicate(10000, mean(rexp(n, rate = 1 / pop_mean)))
# Bootstrap: resample our one sample, with replacement, 10,000 times
boot_means <- replicate(10000, mean(sample(x, replace = TRUE)))
# Compare the spread of the two sampling distributions
round(c(true_SE = sd(fresh_means), bootstrap_SE = sd(boot_means),
formula_SE = sd(x) / sqrt(n)), 3)
# 95% percentile bootstrap confidence interval for the mean
round(quantile(boot_means, c(0.025, 0.975)), 2)
# Does the recipe work? Repeat the whole study 1,000 times
covers <- replicate(1000, {
s <- rexp(n, rate = 1 / pop_mean)
bm <- replicate(1000, mean(sample(s, replace = TRUE)))
ci <- quantile(bm, c(0.025, 0.975))
ci[1] <= pop_mean && pop_mean <= ci[2]
})
mean(covers) # share of intervals that caught the true meanPython
import numpy as np
rng = np.random.default_rng(26088)
# A skewed "population" we normally never get to see: waiting times, mean 10
pop_mean = 10
n = 40
# The one sample we actually have
x = rng.exponential(scale=pop_mean, size=n)
print(round(x.mean(), 2))
# God's-eye view: draw 10,000 fresh samples from the population
fresh_means = rng.exponential(scale=pop_mean, size=(10000, n)).mean(axis=1)
# Bootstrap: resample our one sample, with replacement, 10,000 times
boot_means = rng.choice(x, size=(10000, n), replace=True).mean(axis=1)
# Compare the spread of the two sampling distributions
print({"true_SE": round(fresh_means.std(ddof=1), 3),
"bootstrap_SE": round(boot_means.std(ddof=1), 3),
"formula_SE": round(x.std(ddof=1) / np.sqrt(n), 3)})
# 95% percentile bootstrap confidence interval for the mean
# (NumPy's default quantile method is the same as R's default, type 7)
print(np.round(np.quantile(boot_means, [0.025, 0.975]), 2))
# Does the recipe work? Repeat the whole study 1,000 times
covers = []
for _ in range(1000):
s = rng.exponential(scale=pop_mean, size=n)
bm = rng.choice(s, size=(1000, n), replace=True).mean(axis=1)
lo, hi = np.quantile(bm, [0.025, 0.975])
covers.append(lo <= pop_mean <= hi)
print(np.mean(covers)) # share of intervals that caught the true meanThe figures below come from one seeded run of the R code. Python uses a different random number generator, so its figures differ slightly, but they show the same pattern.
- The one sample had a mean of 8.93, a bit below the true 10, as samples usually miss by a little.
- The spread matched well. The true standard error, from 10,000 fresh samples, was 1.582. The bootstrap, using nothing but the 40 observations, estimated 1.366, and the textbook formula gave 1.398. The bootstrap and the formula agree closely, and both run a little low here because this particular sample happened to be less spread out than the population.
- The interval was 6.43 to 11.77, which contains the true mean.
- Across 1,000 repeated studies, 91.4% of the 95% intervals captured the true mean: close to the target, but slightly short. Simple percentile intervals tend to undercover a little with small, skewed samples.
The same code works for a median or any other statistic: replace mean with the function you care about. That flexibility is the real selling point, since for many statistics no textbook formula exists.
When the bootstrap does not work well
The method is only as good as the stand-in. It breaks down when the sample is a poor miniature of the population:
- Very small samples. With 10 observations, the jar is a crude copy of the warehouse, and the bootstrap tends to understate uncertainty. It cannot invent values it has never seen.
- Biased samples. If the scoop was not random, resampling it faithfully reproduces the bias. The bootstrap measures random wobble, not systematic error.
- Extremes. For the maximum or minimum, the bootstrap fails because a resample can never exceed the largest value you observed. Very heavy-tailed data cause similar trouble.
- Dependent data. Time series or clustered observations must be resampled in blocks or whole clusters. Shuffling individual points destroys the structure that drives the real uncertainty.
For better small-sample intervals, the bias-corrected and accelerated (BCa) interval, available through boot.ci() in the recommended R package boot, usually gets closer to the nominal coverage than the simple percentile interval shown above. Use at least a few thousand resamples for intervals; the extra computation is cheap.
How to Report (APA 7th)
Name the interval type and the number of resamples, so readers can judge and reproduce the result. Using the sample above, an inline write-up could read:
The mean waiting time was 8.93 minutes, 95% CI [6.43, 11.77], based on a percentile bootstrap with 10,000 resamples.
In the method section, add one sentence such as: Confidence intervals were estimated by nonparametric bootstrapping (10,000 resamples with replacement; percentile method). If you use BCa intervals, say so, and report the random seed or software in supplementary material. For more on what the interval itself means, see our page on what 95% confidence actually means.
Related tools and guides
- Which statistical test should I use?
- What does 95% confidence actually mean?
- Where does the 1/sqrt(n) margin of error come from?
- Bootstrapping (Wikipedia)
More answered questions
- Where does the 1/sqrt(n) margin of error come from?
- Is there a 95% probability that your confidence interval covers the true mean?
Working with your own data?
General answers only go so far. Send us your situation and we'll reply by email within two business days.
Ask your questionWritten by AskStats with AI assistance. This is general information, not advice for your specific data or study. When the results matter, check your approach with a qualified statistician.