Confidence intervals with bootstrapping

Warm up

Announcements

  • Exam:
    • In class: Fri, June 7th (1 sheet of notes allowed)
    • Take home due Sun, June 9th

Packages

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.4.4     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ purrr::%||%()   masks base::%||%()
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(tidymodels)
── Attaching packages ────────────────────────────────────── tidymodels 1.1.1 ──
✔ broom        1.0.5          ✔ rsample      1.2.0     
✔ dials        1.2.0          ✔ tune         1.1.2     
✔ infer        1.0.5.9000     ✔ workflows    1.1.3     
✔ modeldata    1.2.0          ✔ workflowsets 1.0.1     
✔ parsnip      1.1.1          ✔ yardstick    1.2.0     
✔ recipes      1.0.8          
── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
✖ purrr::%||%()     masks base::%||%()
✖ scales::discard() masks purrr::discard()
✖ dplyr::filter()   masks stats::filter()
✖ recipes::fixed()  masks stringr::fixed()
✖ dplyr::lag()      masks stats::lag()
✖ yardstick::spec() masks readr::spec()
✖ recipes::step()   masks stats::step()
• Use tidymodels_prefer() to resolve common conflicts.
library(openintro)
Loading required package: airports
Loading required package: cherryblossom
Loading required package: usdata

Attaching package: 'openintro'

The following object is masked from 'package:modeldata':

    ames

Confidence intervals

Case study 3: Airbnb in Asheville, NC

We have data on the price per guest (ppg) for a random sample of 50 Airbnb listings in 2020 for Asheville, NC. We are going to use these data to investigate what we would of expected to pay for an Airbnb in in Asheville, NC in June 2020.

abb <- read_csv("asheville.csv")

glimpse(abb)
Rows: 50
Columns: 1
$ ppg <dbl> 48.00000, 40.00000, 99.00000, 13.00000, 55.00000, 75.00000, 74.000…

Terminology

  • Population parameter - What we are interested in. Statistical measure that describes an entire population.

  • Sample statistic (point estimate) - describes a sample. A piece of information you get from a fraction of the population.

abb |> 
  summarize(ppg.mean = mean(ppg))
# A tibble: 1 × 1
  ppg.mean
     <dbl>
1     76.6

Catching a fish

Suppose you’re fishing in a murky lake. Are you more likely to catch a fish using a spear or a net?

  • Spear \(\rightarrow\) point estimate
  • Net \(\rightarrow\) interval estimate

Constructing confidence intervals

Quantifying the variability of the sample statistics to help calculate a range of plausible values for the population parameter of interest:

  • Via simulation \(\rightarrow\) using bootstrapping – using a statistical procedure that re samples a single data set to create many simulated samples.

  • Via mathematical formulas \(\rightarrow\) using the Central Limit Theorem

Bootstrapping, what?

  • The term bootstrapping comes from the phrase “pulling oneself up by one’s bootstraps”, which is a metaphor for accomplishing an impossible task without any outside help.

  • Impossible task: estimating a population parameter using data from only the given sample.

Note

Note: This notion of saying something about a population parameter using only information from an observed sample is the crux of statistical inference, it is not limited to bootstrapping.

Bootstrapping, how?

  • Resample with replacement from our data \(n\) times, where \(n\) is the sample size
  • Calculate the sample statistic of interest of the new, resampled (bootstrapped) sample and record the value
  • Do this entire process many many times to build the bootstrap distribution

Bootstrapping Airbnb rentals

set.seed(25) 

boot_dist_abb <- abb |>
  specify(response = ppg) |>
  generate(reps = 100, type = "bootstrap") |>
  calculate(stat = "mean")

The bootstrap distribution

glimpse(boot_dist_abb)
Rows: 100
Columns: 2
$ replicate <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 1…
$ stat      <dbl> 73.11500, 78.78333, 80.19333, 83.42000, 70.15000, 73.03667, …

Visualzing the bootstrap distribution

What do you expect the center of the bootstrap distribution to be? Why? Check your guess by visualizing the distribution.

ggplot(boot_dist_abb, aes(x = stat)) + 
  geom_histogram()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Calculating the bootstrap distribution

boot_dist_abb |>
  summarize(
    lower = quantile(stat, 0.025),
    upper = quantile(stat, 0.975)
  )
# A tibble: 1 × 2
  lower upper
  <dbl> <dbl>
1  64.7  89.6

Interpretation

Which of the following is the correct interpretation of the bootstrap interval?

  1. There is a 95% probability the true mean price per night for an Airbnb in Asheville is between $64.7 and $89.6.

  2. There is a 95% probability the price per night for an Airbnb in Asheville is between $64.7 and $89.6.

  3. We are 95% confident the true mean price per night for Airbnbs in Asheville is between $64.7 and $89.6.

  4. We are 95% confident the price per night for an Airbnb in Asheville is between $64.7 and $89.6.

Leveraging tidymodels tools further

Calculating the observed sample statistic:

obs_stat_abb <- abb |>
  specify(response = ppg) |>
  calculate(stat = "mean")  

obs_stat_abb
Response: ppg (numeric)
# A tibble: 1 × 1
   stat
  <dbl>
1  76.6

Leveraging tidymodels tools further

Calculating the interval:

ci_95_abb <- boot_dist_abb |>
  get_confidence_interval(
    point_estimate = obs_stat_abb, 
    level = 0.95
  )

ci_95_abb
# A tibble: 1 × 2
  lower_ci upper_ci
     <dbl>    <dbl>
1     64.7     89.6

Leveraging tidymodels tools further

Visualizing the interval:

visualize(boot_dist_abb) +
  shade_confidence_interval(ci_95_abb)