Lesson 6 of 7

The Bootstrap and the Jackknife+

Every interval and probability you have built so far leaned on a model's assumptions: a bell-shaped error, an equal spread, a logistic squashing. This lesson gets uncertainty a different way, one that assumes almost nothing. You take the single dataset you already have and resample it, over and over, letting the data itself show you how much your answer could have wobbled.

Meet Rohan again, the real-estate agent from the first lessons. He has just closed on 50 homes in one neighborhood, and he owes two honest numbers. First, a headline for his market report: "the typical home here sells for about \$330,000." How sure is that \$330,000? Second, a quote for one specific new listing, a 2000 square-foot home: not just a price, but a range he can stand behind. By the end you will answer both from those same 50 rows, with no bell curve in sight.

By the end of this lesson you will be able to:

  • Explain what a bootstrap resample is and why the spread of a statistic across many resamples estimates its sampling distribution
  • Compute a bootstrap standard error and a percentile confidence interval in R for a statistic that has no textbook formula
  • Build a jackknife+ prediction interval from leave-one-out residuals, and check that its coverage holds the guarantee

Prerequisites: Lessons 1 to 2 of this course (a prediction interval, coverage, empirical coverage, and the held-out split idea behind split conformal, which the jackknife+ is the leave-one-out cousin of). A residual is actual minus predicted; you can fit lm(price ~ sqft) and call predict(). Base R: sample(), x[idx] indexing, for loops, quantile(). Every new term is defined as it appears.

Where we left off

One dataset, two honest questions

In Lesson 5 you put Nadia's rain probabilities on trial and learned to repair them. That fix, like every method in this course so far, trusted an assumption: calibration leaned on a logistic shape, Lesson 1's textbook band leaned on a symmetric bell curve. When an assumption cracks, the promise on the label quietly becomes fiction, exactly what happened to Rohan's biggest homes back in Lesson 2.

The bootstrap refuses to lean on any of that. Its one idea is almost cheeky: your sample is your best picture of the population, so to see how a statistic would vary across other samples you never got to collect, just draw fresh samples from the sample you have. Let us rebuild Rohan's 50 sales so we can try it. Each lesson runs in a fresh R session, so we create the data right here (run this once). Home sizes are right-skewed, the way a real market is (lots of mid-size homes, a few large ones), and price climbs with size plus noise.

RInteractive R
set.seed(1) n <- 50 sqft <- round(exp(rnorm(n, log(1500), 0.35))) # home sizes, right-skewed like a real market price <- round(60000 + 175 * sqft + rnorm(n, 0, 20000)) # price grows with size, plus noise homes <- data.frame(sqft, price) head(homes, 4) #> sqft price #> 1 1205 278837 #> 2 1600 327759 #> 3 1120 262822 #> 4 2622 496263 c(mean = round(mean(price)), median = round(median(price))) #> mean median #> 345049 330214

  

Notice the mean (\$345,049) sits well above the median (\$330,214). A few large homes drag the average up, which is exactly why real-estate reports quote the median sale price, not the mean. So the median is the number Rohan will headline. Now, how precise is it?

For the mean there is a famous formula for the uncertainty. The standard error of a statistic is the standard deviation of that statistic across many hypothetical samples, in words, the typical amount it would jump around if Rohan had happened to sell 50 different homes. For the mean it is the sample standard deviation \(s\) divided by \(\sqrt{n}\):

\[ \text{SE}(\bar x) \;=\; \frac{s}{\sqrt{n}}, \]

where \(\bar x\) is the sample mean, \(s\) is the sample standard deviation of the prices, and \(n = 50\) is the number of homes.

RInteractive R
se_mean <- sd(price) / sqrt(n) round(c(sample_mean = mean(price), se_of_the_mean = se_mean)) #> sample_mean se_of_the_mean #> 345049 11036

  

So the mean is good to about \$11,000 either side. But there is no such clean formula for the median. That is the gap the bootstrap fills.