-
Notifications
You must be signed in to change notification settings - Fork 539
Expand file tree
/
Copy path08-confidence-intervals.qmd
More file actions
executable file
·2176 lines (1594 loc) · 147 KB
/
Copy path08-confidence-intervals.qmd
File metadata and controls
executable file
·2176 lines (1594 loc) · 147 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
description: &desc "Construct percentile- and standard-error-based bootstrap confidence intervals using the infer workflow: specify → generate → calculate."
open-graph:
description: *desc
twitter-card:
description: *desc
---
```{r setup-init, include=FALSE}
library(knitr)
source("scripts/image_functions.R")
```
# Estimation, Confidence Intervals, and Bootstrapping {#sec-confidence-intervals}
::: {.callout-note title="In this chapter, you'll learn how to:"}
- Construct a *bootstrap distribution* using the `infer` workflow (`specify` → `generate` → `calculate`)
- Build *percentile-based* and *standard-error-based* confidence intervals
- Interpret a confidence interval in plain language (avoiding common misinterpretations)
- Connect the bootstrap distribution to the theoretical sampling distribution
:::
```{r setup_ci, include=FALSE, purl=FALSE}
# Used to define Learning Check numbers:
chap <- 8
lc <- 0
# Set R code chunk defaults:
knitr::opts_chunk$set(
echo = TRUE,
eval = TRUE,
warning = FALSE,
message = TRUE,
tidy = FALSE,
purl = TRUE,
out.width = "\\textwidth",
# fig.height = 4,
fig.align = "center"
)
# Set output digit precision
options(scipen = 99) # , digits = 3)
options(pillar.sigfig = 6)
# Set random number generator seed value for replicable pseudo-randomness.
set.seed(76)
```
```{r lc-inline-setup-08, include=FALSE, purl=FALSE}
source("scripts/lc_solutions.R")
lc_setup(8)
```
```{r confidence-intervals-load-packages, echo=FALSE, message=FALSE, purl=FALSE}
library(dplyr)
library(moderndive)
library(tidyverse)
library(knitr)
```
```{r confidence-intervals-compute-mean, echo=FALSE, purl=FALSE}
# This code is used for dynamic non-static in-line text output purposes
p_red <- bowl |>
summarize(mean(color == "red")) |>
pull()
n_balls_sample <- 50L # sample size for the bowl with balls activity
n_virtual_resample <- 1000L # number of bootstrap samples used in this chapter
n_manual_rep <- 35L # number of bootstrap sample when pretending a study manually
```
We studied sampling in @sec-sampling. Recall, for example, getting many random samples of red and white balls from a bowl, finding the sample proportions of red balls from each of those samples, and studying the distribution of the sample proportions. We can summarize our findings as follows:
- the sampling distribution of the sample proportion follows, approximately, the normal distribution,
- the expected value of the sample proportion, located at the center of the distribution, is exactly equal to the population proportion, and
- the sampling variation, measured by the standard error of the sample proportion, is equal to the standard deviation of the population divided by the square root of the sample size used to collect the samples.
Similarly, when sampling chocolate-covered almonds and getting the sample mean weight from each sample, the characteristics described above are also encountered in the sampling distribution of the sample mean; namely,
- the sampling distribution of the sample mean follows, approximately, the normal distribution;
- the expected value of the sample mean is the population mean, and
- the standard error of the sample mean is the standard deviation of the population divided by the square root of the sample size.
Moreover, these characteristics also apply to sampling distributions for the difference in sample means, the difference in sample proportions, and others. Recall that the sampling distribution is not restricted by the distribution of the population. As long as the samples taken are fairly large and we use the appropriate standard error, we can generalize these results appropriately.
The study of the sampling distribution is motivated by another question we have not yet answered: how can we determine the average weight of all the almonds if we do not have access to the entire bowl? We have seen by using simulations in @sec-sampling that the average of the sample means, derived from many random samples, will be fairly close to the expected value of the sample mean, which is precisely the population mean weight.
However, in real-life situations, we do not have access to many random samples, only to a single random sample. This chapter introduces methods and techniques that can help us approximate the information of the entire population, such as the population mean weight, by using a single random sample from this population. This undertaking is called __estimation__, and it is central to Statistics and Data Science.
We introduce some statistical jargon about estimation. If we are using a sample statistic to __estimate__ a population parameter, e.g., using the sample mean from a random sample to estimate the population mean, we call this statistic a __point estimate__ to make emphasis that it is a single value that is used to estimate the parameter of interest.
Now, you may recall that, due to sampling variation, the sample mean typically does not match the population mean exactly, even if the sample is large.
To account for this variation, we use an interval to estimate the parameter instead of a single value, and appropriately call it an __interval estimate__ or, if given some level of accuracy, a __confidence interval__ of the population parameter. In this chapter, we explain how to find confidence intervals, the advantages of using them, and the different methods that can be used to determine them.
In @sec-theory-based-CI we introduce a method to build a confidence interval for the population mean that uses the random sample taken and theoretical characteristics of the sampling distribution discussed in @sec-sampling.
We call this the theory-based approach for constructing intervals.
In @sec-simulation-based-CI we introduce another method, called the bootstrap, that produces confidence intervals by resampling a large number of times from the original sample. Since resampling is done via simulations, we call this the simulation-based approach for constructing confidence intervals. <!-- In @sec-theory-ci we provide some theoretical foundations to explain the logic behind the bootstrap, introduce some alternatives within this approach, compare it with the theory-based approach, and show the advantages and disadvantages of different approaches. -->
Finally, in @sec-summary-CI we summarize and present extensions of these methods.
## Needed packages {.unnumbered #sec-CI-packages}
If needed, read @sec-packages for information on how to install and load R packages.
```{r confidence-intervals-example-load-packages-2, message=FALSE}
library(tidyverse)
library(moderndive)
library(infer)
```
Recall that loading the `tidyverse` package loads many packages that we have encountered earlier. For details refer to @sec-tidyverse-package. The packages `moderndive` and `infer` contain functions and data frames that will be used in this chapter.
```{r confidence-intervals-load-internal, message=FALSE, echo=FALSE, purl=FALSE}
# Packages needed internally, but not in the text
library(knitr)
library(kableExtra)
library(patchwork)
library(purrr)
library(scales)
library(knitr)
library(ggrepel)
```
## Tying the sampling distribution to estimation {#sec-theory-based-CI}
In this section we revisit the chocolate-covered almonds example introduced in @sec-sampling and the results from the sampling distribution of the sample mean weight of almonds, but this time we use this information in the context of estimation.
We start by introducing or reviewing some terminology using the almonds example. The bowl of chocolate-covered almonds is the population of interest. The parameter of interest is the *population mean* weight of almonds in the bowl, $\mu$. This is the quantity we want to estimate.
We want to use the sample mean to estimate this parameter. So we call the sample mean an **estimator** or an **estimate** of $\mu$, the population mean weight.
The difference between estimator and estimate is worth discussing.
As an illustration, we decide to take a random sample of 100 almonds from the bowl and use its sample mean weight to estimate the population mean weight. In other words, we intend to sum 100 almonds' weights, divide this sum by 100, and use this value to estimate the population mean weight. When we refer to the *sample mean* to describe this process via an equation, the sample mean weight is called an **estimator** of the population mean weight.
Since different samples produce different sample means, the sample mean as an estimator is the random variable $\overline X$ described in @sec-random-variable-sample-mean. As we have learned studying the sampling distribution in @sec-sampling, we know that this **estimator** follows, approximately, a normal distribution; its expected value is equal to the population mean weight. Its standard deviation, also called standard error, is
$$SE(\bar x) = \frac{\sigma}{\sqrt{n}}$$
where $n = 100$ in this example and $\sigma$ is the population standard deviation of almonds' weights.
We took a random sample of 100 almonds' weights such as the one shown here and stored it in the `moderndive` package with the same name:
```{r confidence-intervals-create-almonds_sample_1, echo=FALSE}
almonds_sample_100 <- moderndive::almonds_sample_100
```
```{r confidence-intervals-demo-code}
almonds_sample_100
```
```{r confidence-intervals-compute-mean-sized, echo=FALSE, purl=FALSE}
# This code is used for dynamic non-static in-line text output purposes
# x_bar is the mean almonds' weight of the original sample of size n=100
x_bar <- almonds_sample_100 |>
summarize(mean_weight = mean(weight)) |>
pull(mean_weight)
```
We can use it to calculate the sample mean weight:
```{r confidence-intervals-compute-mean-alt2}
almonds_sample_100 |>
summarize(sample_mean = mean(weight))
```
```{r confidence-intervals-create-xbar, echo=FALSE}
xbar <- mean(almonds_sample_100$weight)
```
Then $\overline{x} = `r xbar`$ grams is an **estimate** of the population mean weight.
In summary, the **estimator** is the procedure, equation, or method that will be used on a sample to estimate a parameter before the sample has been retrieved and has many useful properties discussed in @sec-sampling. The moment a sample is taken and the equation of a sample mean is applied to this sample, the resulting number is an **estimate**.
The sample mean, as an estimator or estimate of the population mean, will be a central component of the material developed in this chapter.
But, note that it is not the only quantity of interest.
For example, the *population standard deviation* of the almonds' weight, denoted by the Greek letter $\sigma$, is a parameter and the *sample standard deviation* can be an **estimator** or **estimate** of this parameter.
Furthermore, we have shown in @sec-sampling that the expected value of the sample mean is equal to the population mean. When this happens, we call the sample mean an **unbiased** estimator of the population mean. This does not mean that any sample mean will be equal to the population mean; some sample means will be greater while others will be smaller but, on average, they will be equal to the population mean. In general, when the expected value of an estimator is equal to the parameter it is trying to estimate, we call the estimator **unbiased**. If it is not, the estimator is **biased**.
We now revisit the almond activity and study how the sampling distribution of the sample mean can help us build interval estimates for the population mean.
::: {.learncheck}
**Learning Check**
**`r paste0("(LC", chap, ".", (lc <- lc + 1), ")")`** What is the expected value of the sample mean weight of almonds in a large sample according to the sampling distribution theory?
- A. It is always larger than the population mean.
- B. It is always smaller than the population mean.
- C. It is exactly equal to the population mean.
- D. It is equal to the population mean on average but may vary in any single sample.
```{r lc-sol-08-01, echo=FALSE, results='asis', purl=FALSE}
cat(lc_solution(8, 1))
```
**`r paste0("(LC", chap, ".", (lc <- lc + 1), ")")`** What is a **point estimate** and how does it differ from an **interval estimate** in the context of statistical estimation?
- A. A point estimate uses multiple values to estimate a parameter; an interval estimate uses a single value.
- B. A point estimate is a single value used to estimate a parameter; an interval estimate provides a range of values within which the parameter likely falls.
- C. A point estimate is the mean of multiple samples; an interval estimate is the median.
- D. A point estimate and an interval estimate are the same and can be used interchangeably.
```{r lc-sol-08-02, echo=FALSE, results='asis', purl=FALSE}
cat(lc_solution(8, 2))
```
:::
```{r confidence-intervals-create-num_almonds, echo=FALSE}
num_almonds <- nrow(almonds_bowl)
mu <- mean(almonds_bowl$weight)
sigma <- pop_sd(almonds_bowl$weight)
```
### Revisiting the almond activity for estimation {#sec-revisit-almond}
In @sec-sampling, one of the activities was to take many random samples of size 100 from a bowl of 5,000 chocolate-covered almonds. Since we have access to the contents of the entire bowl, we can compute the population parameters:
```{r confidence-intervals-mean-and-sd}
almonds_bowl |>
summarize(population_mean = mean(weight),
population_sd = pop_sd(weight))
```
The total number of almonds in the bowl is 5,000. The population mean is
$$\mu = \sum_{i=1}^{5000}\frac{x_i}{5000}=`r mu`,$$
and the population standard deviation, [`pop_sd()`](https://moderndive.github.io/moderndive/reference/pop_sd.html), from `moderndive`, is defined as
$$\sigma = \sqrt{\sum_{i=1}^{5000} \frac{(x_i - \mu)^2}{5000}}=`r sigma`.$$
We keep those numbers for future reference to determine how well our methods of estimation are doing, but recall that in real-life situations we do not have access to the population values and the population mean $\mu$ is unknown. All we have is the information from one random sample. In our example, we assume that all we know is the `almonds_sample_100` object stored in `moderndive`.
Its `ID` variable shows the almond chosen from the bowl and its corresponding `weight`. Using this sample we calculate some sample statistics:
```{r confidence-intervals-mean-sd}
almonds_sample_100 |>
summarize(mean_weight = mean(weight),
sd_weight = sd(weight),
sample_size = n())
```
In one of the activities performed in @sec-sampling we took many random samples, calculated their sample means, constructed a histogram using these sample means, and showed how the histogram is a good approximation of the sampling distribution of the sample mean.
We redraw @fig-sample-mean-100-with-normal here as @fig-sample-mean-100-with-normal-redraw.
```{r fig-sample-mean-100-with-normal-redraw, fig.alt="Histogram of the sampling distribution of the sample mean (n=100) with the corresponding normal density curve overlaid.", echo=FALSE, fig.height=ifelse(knitr::is_latex_output(), 1.9, 4), fig.cap="The distribution of the sample mean.", purl=FALSE}
num_almonds_sample <- length(almonds_sample_100$weight)
xbar <- mean(almonds_sample_100$weight)
if (!file.exists("rds/virtual_mean_weight_100.rds")) {
set.seed(2)
virtual_mean_weight_100 <- almonds_bowl |>
rep_slice_sample(n = num_almonds_sample, replace = TRUE, reps = 1000) |>
summarize(mean_weight = mean(weight), n = n())
write_rds(virtual_mean_weight_100, "rds/virtual_mean_weight_100.rds")
} else {
virtual_mean_weight_100 <- read_rds("rds/virtual_mean_weight_100.rds")
}
almond_100_mean <- mean(almonds_sample_100$weight)
ggplot(virtual_mean_weight_100, aes(x = mean_weight)) +
geom_histogram(aes(y = after_stat(density)), binwidth = 0.01,
color = "white") +
stat_function(fun = dnorm,
args = list(mean = mu, sd = sigma/sqrt(num_almonds_sample)),
col = "red") +
labs(x = "Sample means with n=100") +
annotate("point", x = mean(almonds_sample_100$weight), y = 0,
color = "blue") +
annotate("point", x = mu, y = 0, color = "red") +
annotate("text", x = mu, y = -1, label = "mu", parse = TRUE, color = "red") +
annotate("text", x = mean(almonds_sample_100$weight), y = -1,
label = "bar(x)", parse = TRUE, color = "blue")
```
The histogram in @fig-sample-mean-100-with-normal-redraw is drawn using many sample mean weights from random samples of size $n=100$.
The added `r if(is_html_output()) "red"` smooth curve is the density curve for the normal distribution with the appropriate expected value and standard error calculated from the sampling distribution.
The `r ifelse(is_html_output(), "red", "left")` dot represents the population mean $\mu$, the unknown parameter we are trying to estimate. The `r ifelse(is_html_output(), "blue", "right")` dot is the sample mean $\overline{x} = `r xbar`$ from the random sample stored in `almonds_sample_100`.
In real-life applications, a sample mean is taken from a sample, but the distribution of the population and the population mean are unknown, so the location of the `r ifelse(is_html_output(), "blue", "right")` dot with respect to the `r ifelse(is_html_output(), "red", "left")` dot is also unknown. However, if we construct an interval centered on the `r ifelse(is_html_output(), "blue", "right")` dot, as long as it is wide enough the interval will contain the `r ifelse(is_html_output(), "red", "left")` dot.
To understand this better, we need to learn a few additional properties of the normal distribution.
### The normal distribution
A random variable can take on different values. When those values can be represented by one or more intervals, the likelihood of those values can be expressed graphically by a density curve on a Cartesian coordinate system in two dimensions. The horizontal axis (X-axis) represents the values that the random variable can take and the height of density curve (Y-axis) provides a graphical representation of the likelihood of those values; the higher the curve the more likely those values are. In addition, the total area under a density curve is always equal to 1. The set of values a random variable can take alongside their likelihood is what we call the distribution of a random variable.
The normal distribution \index{distribution!normal} is the distribution of a special type of random variable. Its density curve has a distinctive bell shape, and it is fully defined by two values: (1) the mean or expected value of the random variable, $\mu$, which is located on the X-axis at the center of the density curve (its highest point), and (2) the standard deviation, $\sigma$, which reflects the dispersion of the random variable; the greater the standard deviation is the wider the curve appears.
In @fig-normal-curves, we plot the density curves of three random variables, all following normal distributions:
1. The solid line represents a normal distribution with $\mu = 5$ \& $\sigma = 2$.
1. The dotted line represents a normal distribution with $\mu = 5$ \& $\sigma = 5$.
1. The dashed line represents a normal distribution with $\mu = 15$ \& $\sigma = 2$.
```{r fig-normal-curves, fig.alt="Three normal density curves overlaid: a tall narrow curve, a wider one with the same mean, and a third curve shifted to a different mean.", echo=FALSE, fig.cap="Three normal distributions.", purl=FALSE, fig.height=ifelse(knitr::is_latex_output(), 1, 4)}
all_points <- tibble(
domain = seq(from = -10, to = 25, by = 0.01),
`mu = 5, sigma = 2` = dnorm(x = domain, mean = 5, sd = 2),
`mu = 5, sigma = 5` = dnorm(x = domain, mean = 5, sd = 5),
`mu = 15, sigma = 2` = dnorm(x = domain, mean = 15, sd = 2)
) |>
gather(key = "Distribution", value = "value", - domain) |>
mutate(
Distribution = factor(
Distribution,
levels = c("mu = 5, sigma = 2",
"mu = 5, sigma = 5",
"mu = 15, sigma = 2")
)
)
for_labels <- all_points |>
filter(between(domain, 3.795, 3.805) & Distribution == "mu = 5, sigma = 2" |
between(domain, 0.005, 0.0105) & Distribution == "mu = 5, sigma = 5" |
between(domain, 16.005, 16.015) & Distribution == "mu = 15, sigma = 2")
all_points |>
ggplot(aes(x = domain, y = value, linetype = Distribution)) +
geom_line() +
geom_label_repel(data = for_labels, aes(label = Distribution),
nudge_x = c(-1, -2.1, 1)) +
theme_light() +
scale_linetype_manual(values=c("solid", "dotted", "longdash")) +
theme(
axis.title.y = element_blank(),
axis.title.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
legend.position = "none"
)
```
A random variable that follows a normal distribution can take any values in the real line, but those values (on the X-axis) that correspond to the peak of the density curve are more likely than those corresponding to the tails.
The density curve drawn with a solid line has the same mean as the one drawn with a dotted line, $\mu = 5$, but the former exhibits less dispersion, measured by the standard deviation $\sigma =2$, than the latter, $\sigma = 5$. Since the total area under any density curve is equal to 1, the wider curve has to be shorter in height to preserve this property. On the other hand, the density curve drawn with a solid line has the same standard deviation as the one drawn with a dashed line, $\sigma = 2$, but the latter has a greater mean, $\mu = 15$, than the former, $\mu = 5$, so they do look the same but the latter is centered farther to the right on the X-axis than the former.
#### The standard normal distribution {.unnumbered}
A special normal distribution has mean $\mu$ = 0 and standard deviation $\sigma$ = 1. It is called the *standard normal distribution*, and it is represented by a density curve called the *$z$-curve*\index{distribution!standard normal}. If a random variable $Z$ follows the standard normal distribution, a realization of this random variable is called a standard value or $z$-value. The $z$-value also represents the number of standard deviations above the mean, if positive, or below the mean, if negative. For example, if $z=5$, the value observed represents a realization of the random variable $Z$ that is five standard deviations above the mean, $\mu = 0$.
#### Linear transformations of random variables that follow the normal distribution {.unnumbered}
A linear transformation of a random variable transforms the original variable into a new random variable by adding, subtracting, multiplying, or dividing constants to the original values. The resulting random variable could have a different mean and standard deviation. The most interesting transformation is turning a random variable into another with $\mu = 0$ and $\sigma = 1$. When this happens we say that the random variable has been standardized.
A property of the normal distribution is that any linear transformation of a random variable that follows the normal distribution results in a new random variable that also follows a normal distribution, potentially with different mean and standard deviation. In particular, we can turn any random variable that follows the normal distribution into a random variable that follows the standard normal distribution. For example, if a value $x = 11$ comes from a normal distribution with mean $\mu =5$ and standard deviation $\sigma = 2$, the $z$-value
$$z = \frac{x - \mu}{\sigma} = \frac{11 - 5}{2} = 3$$
is the corresponding value in a standard normal curve. Moreover, we have determined that $x = 11$ for this example is precisely $3$ standard deviations above the mean.
#### Finding probabilities under a density curve {.unnumbered}
When a random variable can be represented by a density curve, the probability that the random variable takes a value in any given interval (on the X-axis) is equal to the area under the density curve for that interval. If we know the equation that represents the density curve, we could use the mathematical technique from calculus known as integration to determine this area. In the case of the normal curve, the integral for any interval does not have a close-form solution, and the solution is calculated using numerical approximations.
```{r confidence-intervals-conditional-text, echo=FALSE, results="asis", purl=FALSE}
if(!is_latex_output())
cat('Please review [Appendix A online](https://moderndive.com/v2/appendixa) where we provide R code to work with different areas, probabilities, and values under a normal density curve. Here, we place focus on the insights of specific values and areas without dedicating time to those calculations.')
```
We assume that a random variable $Z$ follows a standard normal distribution. We would like to know how likely it is for this random variable to take a value that is within one standard deviation from the mean. Equivalently, what is the probability that the observed value $z$ (in the X-axis) is between -1 and 1 as shown in @fig-normal-curve-shaded-1a?
```{r fig-normal-curve-shaded-1a, fig.alt="Standard normal curve with the area between -1 and +1 standard deviations shaded; this area is approximately 68%.", echo=FALSE, fig.height=ifelse(knitr::is_latex_output(), .9, 4), fig.width=3, fig.cap="Normal area within one standard deviation."}
ggplot(data = data.frame(x = c(-4, 4)), aes(x)) +
stat_function(fun = dnorm, args = list(mean = 0, sd = 1)) +
geom_area(stat = "function", fun = dnorm, fill = "grey100", xlim = c(-4, -1)) +
geom_area(stat = "function", fun = dnorm, fill = "grey80", xlim = c(-1, 1)) +
geom_area(stat = "function", fun = dnorm, fill = "grey100", xlim = c(1, 4)) +
labs(x = "z", y = "") +
scale_y_continuous(breaks = NULL) +
scale_x_continuous(breaks = c(-1,1))
```
Calculations show that this area is 0.6827 (68.27%) of the total area under the curve. This is equivalent to saying that the probability of getting a value between $-1$ and 1 on a standard normal is 68.27%. This also means that if a random variable representing an experiment follows a normal distribution, the probability that the outcome of this experiment is within one standard deviation from the mean is 68.27%. Similarly, the area under the standard normal density curve between -2 and 2 is shown in @fig-normal-curve-shaded-2a.
```{r fig-normal-curve-shaded-2a, fig.alt="Standard normal curve with the area between -2 and +2 standard deviations shaded; this area is approximately 95%.", echo=FALSE, fig.height=ifelse(knitr::is_latex_output(), 0.9, 4), fig.width=3, fig.cap="Normal area within two standard deviations."}
ggplot(data = data.frame(x = c(-4, 4)), aes(x)) +
stat_function(fun = dnorm, args = list(mean = 0, sd = 1)) +
geom_area(stat = "function", fun = dnorm, fill = "grey100", xlim = c(-4, -2)) +
geom_area(stat = "function", fun = dnorm, fill = "grey80", xlim = c(-2, 2)) +
geom_area(stat = "function", fun = dnorm, fill = "grey100", xlim = c(2, 4)) +
labs(x = "z", y = "") +
scale_y_continuous(breaks = NULL) +
scale_x_continuous(breaks = c(-2,2))
```
Calculations show that this area is equal to 0.9545 or 95.45%. If a random variable representing an experiment follows a normal distribution, the probability that the outcome of this experiment is within two standard deviations from the mean is 95.45%. It is also common practice to use the exact number of standard deviations that correspond to an area around the mean exactly equal to 95% (instead of 95.45%).
```{r confidence-intervals-conditional-text-dup1, echo=FALSE, results="asis", purl=FALSE}
if(!is_latex_output())
cat('Please see [Appendix A online](https://moderndive.com/v2/appendixa) to produce these or other calculations in R. ')
```
The result is that the area under the density curve around the mean that is exactly equal to 0.95, or 95%, is the area within 1.96 standard deviation from the mean. Remember this number as it will be used a few times in later sections.
In summary, if the possible outcomes of an experiment can be expressed as a random variable that follows the normal distribution, the probability of getting a result that is within one standard deviation from the mean is about 68.27%, within 2 standard deviations form the mean is 95.45%, within 1.96 standard deviations from the mean is 95%, and within 3 standard deviations from the mean is about 99.73%, to name a few.
Spend a few moments grasping this idea; observe, for example, that it is almost impossible to observe an outcome represented by a number that is five standard deviations above the mean as the chances of that happening are near zero. We are now ready to return to our main goal: how to find an interval estimate of the population mean based on a single sample.
::: {.learncheck}
**Learning Check**
**`r paste0("(LC", chap, ".", (lc <- lc + 1), ")")`** What does the population mean ($\mu$) represent in the context of the almond activity?
- A. The average weight of 100 randomly sampled almonds.
- B. The weight of the heaviest almond in the bowl.
- C. The average weight of all 5,000 almonds in the bowl.
- D. The total weight of all almonds in the bowl.
```{r lc-sol-08-03, echo=FALSE, results='asis', purl=FALSE}
cat(lc_solution(8, 3))
```
**`r paste0("(LC", chap, ".", (lc <- lc + 1), ")")`** Which of the following statements best describes the population standard deviation ($\sigma$) in the almond activity?
- A. It measures the average difference between each almond's weight and the sample mean weight.
- B. It measures the average difference between each almond's weight and the population mean weight.
- C. It is equal to the square root of the sample variance.
- D. It is always smaller than the population mean.
```{r lc-sol-08-04, echo=FALSE, results='asis', purl=FALSE}
cat(lc_solution(8, 4))
```
**`r paste0("(LC", chap, ".", (lc <- lc + 1), ")")`** Why do we use the sample mean to estimate the population mean in the almond activity?
- A. Because the sample mean is always larger than the population mean.
- B. Because the sample mean is a good estimator of the population mean due to its unbiasedness.
- C. Because the sample mean requires less computational effort than the population mean.
- D. Because the sample mean eliminates all sampling variation.
```{r lc-sol-08-05, echo=FALSE, results='asis', purl=FALSE}
cat(lc_solution(8, 5))
```
:::
### The confidence interval{#sec-CI-general}
```{r confidence-intervals-create-se_xbar, echo=FALSE}
se_xbar <- sigma / sqrt(num_almonds_sample)
```
We continue using the example where we try to estimate the population mean weight of almonds with a random sample of 100 almonds. We showed in @sec-sampling that the sampling distribution of the sample mean weight of almonds approximates a normal distribution with expected value equal to the population mean weight of almonds and a standard error equal to
$$SE(\bar x) = \frac{\sigma}{\sqrt {100}}.$$
In @sec-revisit-almond we showed that for the population of almonds, $\mu =`r mu`$ grams and $\sigma = `r sigma`$, so the standard error for the sampling distribution is
$$SE(\bar x) = \frac{\sigma}{\sqrt{100}} = \frac{`r sigma`}{\sqrt{100}} = `r se_xbar`$$
grams. In @fig-normal-curve-1 we plot the density curve for this distribution using these values.
```{r fig-normal-curve-1, fig.alt="Normal density curve representing the sampling distribution of the sample mean weight of almonds, centered at the true population mean.", echo=FALSE, fig.cap="Normal density curve for the sample mean weight of almonds.", purl=FALSE, out.width="90%", warning=FALSE, fig.height=ifelse(knitr::is_latex_output(), 3, 4)}
p1 <- ggplot(data = data.frame(x = c(3.5, 3.8)), aes(x)) +
stat_function(fun = dnorm, args = list(mean = mu, sd = sigma/sqrt(num_almonds_sample)), col = "red") +
ylab("") +
scale_y_continuous(breaks = NULL) +
labs(x = "Sample means with n=100") +
annotate("point", x = mean(almonds_sample_100$weight), y = 0, color = "blue") +
annotate("point", x = mu, y = 0, color = "red") +
annotate("text", x = mu, y = -1, label = "mu == 3.64", parse = TRUE, color = "red") +
annotate("text", x = mean(almonds_sample_100$weight), y = -1,
label = "bar(x) == 3.68", parse = TRUE, color = "blue") +
geom_hline(yintercept = 0, col = "red", lty = 2)
p1
```
```{r confidence-intervals-create-sample_mean, echo=FALSE}
sample_mean <- mean(almonds_sample_100$weight)
deviance <- sample_mean - mu
z_almond <- deviance / se_xbar
```
The horizontal axis (X-axis) represents the sample means that we can determine from all the possible random samples of 100 almonds. The `r ifelse(is_html_output(), "red", "left")` dot represents the expected value of the sampling distribution, $\mu = 3.64$, located on the X-axis at the center of the distribution. The density curve's height can be thought of as how likely those sample means are to be observed. For example, it is more likely to get a random sample with a sample mean around $`r mu`$ grams (which corresponds to the highest point of the curve) than it is to get a sample with a sample mean of around $3.5$ grams, since the curve's height is almost zero at that value. The `r ifelse(is_html_output(), "blue", "right")` dot is the sample mean from our sample of 100 almonds, $\overline{x} = `r sample_mean`$ grams. It is located `r deviance` grams above the population mean weight. How far is `r deviance` grams? It is helpful to express this distance in standardized values:
$$\frac{`r sample_mean` - `r mu`}{`r se_xbar`} = `r z_almond`$$
so `r deviance` more grams is about `r z_almond` standard errors above the population mean.
In real-life situations, the population mean, $\mu$, is unknown so the distance from the sample mean to $\mu$ is also unknown.
On the other hand, the sampling distribution of the sample mean follows a normal distribution. Based on our earlier discussion about areas under the normal curve, there is a 95% chance that the value observed is within 1.96 standard deviations from the mean. In the context of our problem, there is a 95% chance that the sample mean weight is within 1.96 standard errors from the population mean weight. As shown earlier, the sample mean calculated in our example was `r z_almond` standard errors above the population mean, well within the reasonable range.
Think about this result. If we were to take a different random sample of 100 almonds, the sample mean will likely be different, but you still have a 95% chance that the new sample mean will be within 1.96 standard errors from the population mean.
We can finally construct an interval estimate that takes advantage of this configuration. We center our interval at the sample mean observed and then extend to each side the magnitude equivalent to 1.96 standard errors. The lower and upper bounds of this interval are:
```{r confidence-intervals-create-lower_bound, echo=FALSE}
lower_bound <- sample_mean - 1.96 * sigma / sqrt(100)
upper_bound <- sample_mean + 1.96 * sigma / sqrt(100)
```
$$\begin{aligned}\left(\overline{x} - 1.96 \frac{\sigma}{\sqrt{n}},\quad \overline{x} + 1.96 \frac{\sigma}{\sqrt{n}}\right) &= \left(`r sample_mean` - 1.96 \cdot \frac{`r sigma`}{\sqrt{100}},\quad `r sample_mean` + 1.96 \cdot \frac{`r sigma`}{\sqrt{100}}\right)\\
&= (`r round(lower_bound, 3)`, `r round(upper_bound, 3)`)\end{aligned}$$
Here is R code that can be used to calculate these lower and upper bounds:
```{r confidence-intervals-compute-mean-v4}
almonds_sample_100 |>
summarize(
sample_mean = mean(weight),
lower_bound = mean(weight) - 1.96 * sigma / sqrt(length(weight)),
upper_bound = mean(weight) + 1.96 * sigma / sqrt(length(weight))
)
```
The functions `mean()` and `length()` find the sample mean weight and sample size, respectively, from the sample of almonds' weights in `almonds_sample_100`. The number 1.96 corresponds to the number of standard errors needed to get a 95% area under the normal distribution and the population standard deviation `sigma` of `r sigma` was found in @sec-revisit-almond. @fig-normal-curve-2 shows this interval as a horizontal `r ifelse(is_html_output(), "blue", "solid")` line. Observe how the population mean $\mu$ is part of this interval.
```{r fig-normal-curve-2, fig.alt="Normal density curve with a shaded interval and a vertical line at the population mean; visually asks whether the mean falls inside or outside the interval.", echo=FALSE, fig.cap="Is the population mean in the interval?", purl=FALSE, out.width="90%", warning=FALSE}
df <- data.frame(x1 = lower_bound, x2 = upper_bound, y1 = 0, y2 = 0)
p1 <- ggplot(data = data.frame(x = c(3.5, 3.8)), aes(x)) +
stat_function(fun = dnorm, args = list(mean = mu, sd = sigma/sqrt(num_almonds_sample)), col="red") + ylab("") +
scale_y_continuous(breaks = NULL) +
labs(title = "The Sampling Distribution of the Sample Mean",
x = "Sample mean weights"
) +
geom_point(aes(x=mean(almonds_sample_100$weight), y=0), color="blue") +
geom_point(aes(x=mu, y=0), color="red") +
annotate(geom="text", x=mu, y=-1, label=bquote("\u03BC"),
color="red") +
annotate(geom="text", x=mean(almonds_sample_100$weight), y=-1, label=bquote("x\u0305"),
color="blue")+
geom_hline(yintercept = 0, col="red", lty=2) +
geom_segment(aes(x = x1, y = y1, xend = x2, yend = y2, colour = "segment"), data = df, col="blue")
p1
```
Since 1.96 standard errors were used on the construction of this interval, we call this a 95% confidence interval. A confidence interval can be viewed as an interval estimator of the population mean. Compare an interval estimator with the sample mean that is a point estimator. The latter estimates the parameter with a single number, the former provides an entire interval to account for the location of the parameter. An apt analogy involves fishing. Imagine that there is a single fish swimming in murky water. The fish is not visible but its movement produces ripples on the surface that can provide some limited information about the fish's location. To capture the fish, one could use a spear or a net. Because the information is limited, throwing the spear at the ripples may capture the fish but likely will miss it.
::: {.callout-warning title="Common mistake"}
**A 95% confidence interval is *not* "a 95% probability that the parameter is in this range."** The population parameter is a fixed (though unknown) number — it's either inside this particular interval or it isn't. The "95%" refers to the *procedure*: if you repeated the sampling-and-CI process many times, about 95% of the resulting intervals would contain the true parameter. The honest interpretation: *"We are 95% confident that the population mean is between X and Y"*, where "confident" refers to the long-run reliability of the method, not the probability of any single interval.
:::
Throwing a net around the ripples, on the other hand, may give a much higher likelihood of capturing the fish. Using the sample mean only to estimate the population mean is like throwing a spear at the ripples in the hopes of capturing the fish. Constructing a confidence interval that may include the population mean is like throwing a net to surround the ripples. Keep this analogy in mind, as we will revisit it in later sections.
::: {.learncheck}
**Learning Check**
**`r paste0("(LC", chap, ".", (lc <- lc + 1), ")")`** How is the standard error of the sample mean weight of almonds calculated in the context of this example?
- A. By dividing the sample mean by the population standard deviation.
- B. By dividing the population standard deviation by the square root of the sample size.
- C. By multiplying the sample mean by the square root of the sample size.
- D. By dividing the population mean by the sample size.
```{r lc-sol-08-06, echo=FALSE, results='asis', purl=FALSE}
cat(lc_solution(8, 6))
```
**`r paste0("(LC", chap, ".", (lc <- lc + 1), ")")`** What does a 95% confidence interval represent in the context of the almond weight estimation?
- A. There is a 95% chance that the sample mean is within 1.96 standard deviations from the population mean.
- B. The interval will contain 95% of the almond weights from the sample.
- C. There is a 95% chance that the population mean falls within 1.96 standard errors from the sample mean.
- D. The sample mean is exactly equal to the population mean 95% of the time.
```{r lc-sol-08-07, echo=FALSE, results='asis', purl=FALSE}
cat(lc_solution(8, 7))
```
:::
### The t distribution {#sec-t-distribution-CI}
Recall that due to the Central Limit Theorem, the sampling distribution of the sample mean was approximately normal with mean equal to the population mean $\mu$ and standard deviation given by the standard error $SE(\overline X) = \sigma/\sqrt{n}$. We can standardize this for any sample mean $\overline{x}$ such that
$$z = \frac{\overline{x} - \mu}{\sigma/\sqrt{n}}$$
is the corresponding value of the standard normal distribution.
In the construction of the interval in @fig-normal-curve-2 we have assumed the population standard deviation, $\sigma$, was known, and therefore we have used it to find the confidence interval. Nevertheless, in real-life applications, the population standard deviation is also unknown.
Instead, we use the sample standard deviation, $s$, from the sample we have, as an estimator of the population standard deviation $\sigma$. Our estimated standard error is given by
$$\widehat{SE}(\overline X) = \frac{s}{\sqrt n}.$$
When using the sample standard deviation to estimate the standard error, we are introducing additional uncertainty in our model. For example, if we try to standardize this value, we get
$$t = \frac{\overline{x} - \mu}{s/\sqrt{n}}.$$
Because we are using the sample standard deviation in this equation and since the sample standard deviation changes from sample to sample, the additional uncertainty makes the values $t$ no longer normal. Instead they follow a new distribution called the $t$ distribution.
The $t$ distribution is similar to the standard normal; its density curve is also bell-shaped, and it is symmetric around zero, but the tails of the $t$ distribution are a little thicker than those of the standard normal.
In addition, the $t$ distribution requires one additional parameter, the degrees of freedom. For sample mean problems, the degrees of freedom needed are exactly $n-1$, the size of the sample minus one. @fig-t-curve-1 shows the density curves of
- the standard normal density curve, in black,
- a $t$ density curve for a t distribution with 2 degrees of freedom, in `r ifelse(is_latex_output(), "dotted", "dotted blue")`, and
- a $t$ density curve for a t distribution with 10 degrees of freedom, in `r ifelse(is_latex_output(), "dashed", "dashed red")`.
```{r fig-t-curve-1, fig.alt="Three overlaid density curves: the standard normal (tallest) and two t-distributions with different degrees of freedom (slightly heavier tails).", echo=FALSE, fig.cap="The standard normal and two t-distributions.", purl=FALSE, fig.height=ifelse(knitr::is_latex_output(), 2.5, 4)}
# p1 <- ggplot(data = data.frame(x = c(-4, 4)), aes(x)) +
# stat_function(fun = dnorm, args = list(), col="black") + ylab("") +
# stat_function(fun = dt, args = list(df = 2), col="blue") + ylab("") +
# stat_function(fun = dt, args = list(df = 10), col="red") + ylab("") +
#
# scale_y_continuous(breaks = NULL) +
# labs(
# x = "The standard normal and two t-distributions"
# )
# p1
p1 <- ggplot(data = data.frame(x = c(-4, 4)), aes(x)) +
stat_function(fun = dnorm, args = list(), col = "black") +
ylab("") +
stat_function(fun = dt, args = list(df = 2), col = "blue", linetype = "dotted") +
ylab("") +
stat_function(fun = dt, args = list(df = 10), col = "red", linetype = "dashed") +
ylab("") +
scale_y_continuous(breaks = NULL) +
labs(
x = "The standard normal and two t-distributions"
)
p1
```
Observe how the $t$ density curve in `r ifelse(is_latex_output(), "dashed", "dashed red")` ($t$ with 10 degrees of freedom) gets closer to the standard normal density curve, or $z$-curve, in `r ifelse(is_latex_output(), "solid", "solid black")`, than the $t$ curve in `r ifelse(is_latex_output(), "dotted", "dotted blue")` ($t$ with 2 degrees of freedom). The greater the number of degrees of freedom, the closer the $t$ density curve is from the $z$ curve. This change makes our calculations slightly different.
```{r confidence-intervals-conditional-text-v2, echo=FALSE, results="asis", purl=FALSE}
if(!is_latex_output())
cat("Please see [Appendix A online](https://moderndive.com/v2/appendixa) for calculations of probabilities for $t$ density curves with different degrees of freedom.")
```
Using that knowledge, the calculation for our specific example shows that 95% of the sample means are within 1.98 standard errors from the population mean weight. The number of standard errors needed is not that different from before, 1.98 versus 1.96, because the degrees of freedom are fairly large.
Using this information, we can construct the 95% confidence interval based entirely on our sample information and using the sample mean and sample standard deviation. We calculate those values again for `almonds_sample_100`:
```{r confidence-intervals-mean-sd-v2}
almonds_sample_100 |>
summarize(sample_mean = mean(weight), sample_sd = sd(weight))
```
```{r confidence-intervals-mean-sd-v2-dup1, echo=FALSE}
sample_s <- sd(almonds_sample_100$weight)
lower_bound_t <- with(almonds_sample_100,
mean(weight) - 1.98*sd(weight)/sqrt(length(weight)))
upper_bound_t <- with(almonds_sample_100,
mean(weight) + 1.98*sd(weight)/sqrt(length(weight)))
```
Observe that the sample standard deviation is $s = `r sample_s`$ which is not that different from the population standard deviation of $\sigma = `r sigma`$. We again center the confidence interval at the observed sample mean but now extend the interval by 1.98 standard errors to each side. The lower and upper bounds of this confidence interval are:
$$
\begin{aligned}
\left(\overline{x} - 1.98 \frac{s}{\sqrt{n}},\quad \overline{x} + 1.98 \frac{s}{\sqrt{n}}\right) &= \left(`r sample_mean` - 1.98 \cdot \frac{`r sample_s`}{\sqrt{100}}, `r sample_mean` + 1.98 \cdot \frac{`r sample_s`}{\sqrt{100}}\right) \\
&= (`r round(lower_bound_t, 3)`, `r round(upper_bound_t, 3)`)
\end{aligned}
$$
We can also compute these lower and upper bounds:
```{r confidence-intervals-mean-sd-v2-dup2}
almonds_sample_100 |>
summarize(sample_mean = mean(weight), sample_sd = sd(weight),
lower_bound = mean(weight) - 1.98*sd(weight)/sqrt(length(weight)),
upper_bound = mean(weight) + 1.98*sd(weight)/sqrt(length(weight)))
```
The confidence interval computed here, using the sample standard deviation and a $t$ distribution, is almost the same as the one attained using the population standard deviation and the standard normal distribution, the difference is about 0.005 units for the upper and lower bound. This happens because with a sample size of 100, the $t$-curve and $z$-curve are almost identical and also because the sample standard deviation was very similar to the population standard deviation. This does not have to be always the case and occasionally we can observe greater differences; but, in general, the results are fairly similar.
More importantly, the confidence interval constructed here contains the population mean of $\mu = `r mu`$, which is the result we needed. Recall that a confidence interval is an interval estimate of the parameter of interest, the population mean weight of almonds.
We can summarize the results so far:
- If the size used for your random sample is large enough, the sampling distribution of the sample mean follows, approximately, the normal distribution.
- Using the sample mean observed and the standard error of the sampling distribution, we can construct 95% confidence intervals for the population mean. The formula for these intervals (where $n$ is the sample size used) is given by
$$\left(\overline{x} - 1.96 \frac{\sigma}{\sqrt{n}},\quad \overline{x} + 1.96 \frac{\sigma}{\sqrt{n}}\right).$$
- When the population standard deviation is unknown (which is almost always the case), the sample standard deviation is used to estimate the standard error. This produces additional variability and the standardized values follow a $t$ distribution with $n-1$ degrees of freedom. The formula for 95% confidence intervals when the sample size is $n=100$ is given by
$$\left(\overline{x} - 1.98 \frac{s}{\sqrt{100}},\quad \overline{x} + 1.98 \frac{s}{\sqrt{100}}\right).$$
- The method to construct 95% confidence intervals guarantees that in the long-run for 95% of the possible samples, the intervals determined will include the population mean. It also guarantees that 5% of the possible samples will lead to intervals that do not include the population mean.
- As we have constructed intervals with a 95% level of confidence, we can construct intervals with any level of confidence. The only change in the equations will be the number of standard errors needed.
### Interpreting confidence intervals
We have used the sample `almonds_sample_100`, constructed a 95% confidence interval for the population mean weight of almonds, and showed that the interval contained this population mean. This result is not surprising as we expect intervals such as this to include the population mean for 95% of the possible random samples. We repeat this interval construction for many random samples. @fig-almond-mean-cis presents the results for one hundred 95% confidence intervals.
```{r fig-almond-mean-cis, fig.alt="100 horizontal line segments stacked vertically, each representing a 95% confidence interval from a different sample. Most intervals cross a vertical line at the true population mean; a small number do not (the misses), each flagged in a different color.", fig.cap="One hundred 95% confidence intervals and whether the population mean is captured in each.", echo=FALSE, fig.height=ifelse(knitr::is_latex_output(), 5, 5), purl=FALSE}
set.seed(202)
# Compute data frame with sampled data, sample means, and ci
almond_mean_cis <- almonds_bowl |>
rep_sample_n(size = 100, reps = 100, replace = FALSE) |>
summarize(sample_mean = mean(weight), sample_sd = sd(weight), size = n()) |>
mutate(lower_bound = sample_mean - qt(.975,size-1)*sample_sd/sqrt(size),
upper_bound = sample_mean + qt(.975,size-1)*sample_sd/sqrt(size),
captured = lower_bound <= mu & upper_bound >= mu)
# Plot them!
ggplot(almond_mean_cis) +
geom_segment(aes(
y = replicate, yend = replicate, x = lower_bound, xend = upper_bound,
alpha = factor(captured, levels = c("TRUE", "FALSE"))
)) +
labs(
x = expression("Sample mean weight of almonds"),
y = "Confidence interval number",
alpha = "Captured"
) +
geom_vline(xintercept = mu, color = "red") +
# coord_cartesian(xlim = c(3.45, 3.8)) +
theme_light() +
theme(
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.minor.x = element_blank()
)
```
Note that each interval was built using a different random sample. The `r ifelse(is_latex_output(), "", "red")` vertical line is drawn at the location of the population mean weight, $\mu = `r mu`$. The horizontal lines represent the one hundred 95% confidence intervals found. The gray confidence intervals cross the `r ifelse(is_latex_output(), "", "red")` vertical line so they contain the population mean. The black confidence intervals do not.
This result motivates the meaning of a 95% confidence interval: If you could construct intervals using the procedure described earlier for every possible random sample, then 95% of these intervals will include the population mean and 5% of them will not.
Of course, in most situations, it would be impractical or impossible to take every possible random sample. Still, for a large number of random samples, this result is approximately correct. In @fig-almond-mean-cis, for example, 5 out of 100 confidence intervals do not include the population mean, and 95% do. It won't always match up perfectly like this, but the proportions should match pretty close to the confidence level chosen.
The term "95% confidence" invites us to think we are talking about probabilities or chances. Indeed we are, but in a subtle way. Before a random sample has been procured, there is a 95% chance that when a confidence interval is constructed using the prospective random sample, this interval will contain the population mean. The moment a random sample has been attained, the interval constructed either contains the population mean or it does not; with certainty, there is no longer a chance involved. This is true even if we do not know what the population mean is.
So the 95% confidence refers to the method or process to be used on a prospective sample. We are confident that if we follow the process to construct the interval, 95% of the time the random sample attained will lead us to produce an interval that contains the population mean.
On the other hand, it would be improper to say that... "there is a 95% chance that the confidence interval contains the population mean." Looking at @fig-almond-mean-cis, each of the confidence intervals either does or does not contain $\mu$. Once the confidence interval is determined, either the population mean is included or not.
In the literature, this explanation has been encapsulated in a short-hand version: we are 95% confident that the interval contains the population parameter. For example, in @sec-t-distribution-CI the 95% confidence interval for the population mean weight of almonds was (`r round(lower_bound_t, 3)`, `r round(upper_bound_t, 3)`), and we would say: "We are 95% confident that the population mean weight of almonds is between `r round(lower_bound_t, 3)` and `r round(upper_bound_t, 3)` grams."
It is perfectly acceptable to use the short-hand statement, but always remember that the 95% confidence refers to the process, or method, and can be thought of as a chance or probability only before the random sample has been acquired. To further ensure that the probability-type of language is not misused, quotation marks are sometimes put around "95% confident" to emphasize that it is a short-hand version of the more accurate explanation.
::: {.learncheck}
**Learning Check**
**`r paste0("(LC", chap, ".", (lc <- lc + 1), ")")`** Why does the $t$ distribution have thicker tails compared to the standard normal distribution?
- A. Because the sample mean is considered more likely to match the population mean closely.
- B. Because the $t$ distribution is designed to work when the data does not follow a normal distribution.
- C. Because it assumes that the sample size is always smaller when applying the $t$ distribution.
- D. Because it accounts for the extra uncertainty that comes from using the sample standard deviation instead of the population standard deviation.
\newpage
```{r lc-sol-08-08, echo=FALSE, results='asis', purl=FALSE}
cat(lc_solution(8, 8))
```
**`r paste0("(LC", chap, ".", (lc <- lc + 1), ")")`** What is the effect of increasing the degrees of freedom on the $t$ distribution?
- A. The tails of the distribution become thicker.
- B. The tails of the distribution become thinner.
- C. The distribution does not change with degrees of freedom.
- D. The distribution becomes skewed to the right.
```{r lc-sol-08-09, echo=FALSE, results='asis', purl=FALSE}
cat(lc_solution(8, 9))
```
:::
#### Understanding the width of a confidence interval {#sec-ci-width .unnumbered}
A confidence interval is an estimator of a population parameter. In the case of the almonds' bowl we constructed a confidence interval for the population mean. The equation to construct a 95% confidence interval was
$$\left(\overline{x} - 1.96 \frac{\sigma}{\sqrt{n}}, \overline{x} + 1.96 \frac{\sigma}{\sqrt{n}}\right)$$
Observe that the confidence interval is centered at the sample mean and it extends to each side 1.96 standard errors $1.96\cdot \sigma / \sqrt{n}$. This quantity is exactly half the width of your confidence interval, and it is called the **margin of error**. The value of the population standard deviation, $\sigma$, is beyond our control, as it is determined by the distribution of the experiment or phenomenon studied. The sample mean, $\overline{x}$, is a result that depends on your random sample exclusively. On the other hand, the number 1.96 and the sample size, $n$, are values that can be changed by the researcher or practitioner. They play an important role on the width of the confidence interval. We study each of them separately.
##### The confidence level {.unnumbered}
We mentioned earlier that the number 1.96 relates to a 95% confidence process but we did not show how to determine this value. The level of confidence is a decision of the practitioner. If you want to be more confident, say 98% or 99% confident, you just need to adjust the appropriate number of standard errors needed. We show how to determine this number, and use @fig-normal-curve-shaded-3a to illustrate this process.
- If the confidence level is 0.95 (or 95%), the area in the middle of the standard normal distribution is 0.95. This area is shaded in @fig-normal-curve-shaded-3a.
- We construct $\alpha = 1 - \text{confidence level} = 1 - 0.95 = 0.05$. Think of $\alpha$ as the total area on both tails.
- Since the normal distribution is symmetric, the area on each tail is $\alpha/2 = 0.05/2 = 0.025$.
- We need the exact number of standard deviations that produces the shaded area. Since the center of a standard normal density curve is zero, as shown in @fig-normal-curve-shaded-3a, and the normal curve is symmetric, the number of standard deviations can be represented by $-q$ and $q$, the same magnitude but one positive and the other negative.
```{r fig-normal-curve-shaded-3a, fig.alt="Standard normal curve with the central 95% area shaded between approximately -1.96 and +1.96 standard deviations.", echo=FALSE, fig.cap="Normal curve with the shaded middle area being 0.95", fig.height=ifelse(knitr::is_latex_output(), 1.5, 4), fig.width=3}
ggplot(data = data.frame(x = c(-4, 4)), aes(x)) +
stat_function(fun = dnorm, args = list(mean = 0, sd = 1)) +
geom_area(stat = "function", fun = dnorm, fill = "grey100", xlim = c(-4, -1.96)) +
geom_area(stat = "function", fun = dnorm, fill = "grey80", xlim = c(-1.96, 1.96)) +
geom_area(stat = "function", fun = dnorm, fill = "grey100", xlim = c(1.96, 4)) +
labs(x = "z", y = "") +
scale_y_continuous(breaks = NULL) +scale_x_continuous(breaks = NULL) +
geom_point(aes(x=0, y=0), color="red") +
geom_point(aes(x=-1.96, y=0), color="red") +
geom_point(aes(x=1.96, y=0), color="red") +
annotate(geom="text", x=-1.96, y=-0.03, label = bquote("-q"),
color="red") +
annotate(geom="text", x=1.96, y=-0.03, label = bquote("q"),
color="red") +
annotate(geom="text", x=0, y=-0.04, label = bquote("0"),
color="red")
```
In R, the function `qnorm()` finds the value of $q$ when the area under this curve to the left of this value $q$ is given. In our example the area to the left of $-q$ is $\alpha/2 = 0.05/2 = 0.025$, so
```{r confidence-intervals-demo-code-v2}
qnorm(0.025)
```
or 1.96 standard deviation below the mean. Similarly, the total area under the curve to the left of $q$ is the total shaded area, 0.95, plus the small white area on the left tail, $0.025$, and $0.95 + 0.025 = 0.975$, so
```{r confidence-intervals-demo-code-v2-dup1}
qnorm(0.975)
```
That is the reason we use 1.96 standard deviation when calculating 95% confidence intervals. What if we want to retrieve a 90% confidence interval? We follow the same procedure:
- The confidence level is 0.90.
- $\alpha = 1 - \text{confidence level} = 1 - 0.90 = 0.10$.
- The area on each tail is $\alpha/2 = 0.10/2 = 0.05$.
- The area needed to find $q$ is $0.90+0.05 = 0.95$.
```{r confidence-intervals-v25, results='hide'}
qnorm(0.95)
```
```{r confidence-intervals-v26, echo=FALSE, purl=FALSE}
round(qnorm(0.95), 3)
```
If we want to determine a 90% confidence interval, we need to use `r qnorm(0.95)` standard errors in our calculations. We can update the R code to calculate the lower and upper bounds of a 90% confidence interval:
```{r confidence-intervals-compute-mean-v5}
almonds_sample_100 |>
summarize(sample_mean = mean(weight),
lower_bound = mean(weight) - qnorm(0.95)*sigma/sqrt(length(weight)),
upper_bound = mean(weight) + qnorm(0.95)*sigma/sqrt(length(weight)))
```
Let's do one more. If we want an 80% confidence interval, $1 - 0.8 = 0.2$, $0.2/2 = 0.1$, and $0.8+0.1 = 0.9$, so
```{r confidence-intervals-v28, results='hide'}
qnorm(0.9)
```
```{r confidence-intervals-v29, echo=FALSE, purl=FALSE}
round(qnorm(0.9), 3)
```
When you want to calculate an 80%, 90%, or 95% confidence interval, you need to construct your interval using `r qnorm(0.9)`, `r qnorm(0.95)`, or `r qnorm(0.975)` standard errors, respectively. The more confident you want to be, the larger the number of standard errors you need to use, and the wider your confidence interval becomes. But a confidence interval is an estimator of the population mean, the narrower it is, the more useful it is for practical reasons. So there is a trade-off between the width of a confidence interval and the confidence you want to have.
##### The sample size {.unnumbered}
As we studied changes to the confidence level, we can determine how big is the random sample used. The margin of error for a 95% confidence interval is
$$1.96\cdot \frac{\sigma}{\sqrt{n}}.$$
If the sample size increases, the margin of error decreases proportional to the square root of the sample size. For example, if we secure a random sample of size 25, $1/\sqrt{25} = 0.2$, and if we draw a sample of size 100, $1/\sqrt{100} = 0.1$. By choosing a larger sample size, four times larger, we produce a confidence interval that is half the width. This result is worth considering.
A confidence interval is an estimator of the parameter of interest, such as the population mean weight of almonds. Ideally, we would like to build a confidence interval with a high level of confidence, for example, 95% confidence. But we also want an interval that is narrow enough to provide useful information. For example, assume we get the following 95% confidence intervals for the population mean weight of almonds:
- between 2 and 4 grams, or
- between 3.51 and 3.64 grams, or
- between 3.539 and 3.545 grams.
The first interval does not seem useful at all, the second works better, and the third is tremendously accurate, as we are 95% confident that the population mean is within 0.006 grams. Obviously, we always prefer narrower intervals, but there are trade-offs we need to consider. We always prefer high levels of confidence, but the more confident we want to be the wider the interval will be. In addition, the larger the random sample used, the narrower the confidence interval will be. Using a large sample is always a preferred choice, but the trade-offs are often external; collecting large samples could be expensive and time-consuming. The construction of confidence intervals needs to take into account all these considerations.
We have concluded the theory-based approach to construct confidence intervals. In the next section we explore a completely different approach to construct confidence intervals and in later sections we will make comparisons of these methods.
## Estimation with the bootstrap {#sec-simulation-based-CI}
In 1979, Brad Efron published an article introducing a method called the bootstrap \index{bootstrap!statistical reference}[@Efron1979] that is next summarized. A random sample of size $n$ is taken from the population.
This sample is used to find another sample, with replacement, also of size $n$. This is called *resampling with replacement*\index{resampling} and the resulting sample is called a *bootstrap sample*\index{bootstrap}. For example, if the original sample is $\{4,2,5,4,1,3,7,4,6,1\}$, one particular bootstrap sample could be $\{6, 4, 7, 4, 2, 7, 2, 5, 4, 1\}.$
Observe that the number 7 appears once in the original sample, but twice in the bootstrap sample;
similarly, the number 3 in the original sample does not appear in the bootstrap sample. This is not uncommon for a bootstrap sample, some of the numbers in the original sample are repeated and others are not included.
The basic idea of the bootstrap is to gain a large number of bootstrap samples, all drawn from the same original sample. Then, we use all these bootstrap samples to find estimates of population parameters, standard errors, or even the density curve of the population. Using them we can construct confidence intervals, perform hypothesis testing, and other inferential methods.
This method takes advantage of the large number of bootstrap samples that can be determined. In several respects, this exercise is not different from the sampling distribution explained in @sec-sampling. The only difference, albeit an important one, is that we are not sampling from the population, we are sampling from the original sample.
How many different bootstrap samples could we get from a single sample? A very large number, actually. If the original sample has 10 numbers, as the one shown above, each possible bootstrap sample of size 10 is determined by sampling 10 times with replacement, so the total number of bootstrap samples is $10^{10}$ or 10 billion different bootstrap samples. If the original sample has 20 numbers, the number of bootstrap samples is $20^{20}$, a number greater than the total number of stars in the universe.
Even with modern powerful computers, it would be an onerous task to calculate every possible bootstrap sample. Instead, a thousand or so bootstrap samples are retrieved, similar to the simulations performed in @sec-sampling, and this number is often large enough to provide useful results.
Since Efron [@Efron1979] proposed the bootstrap, the statistical community embraced this method. During the 1980s and 1990s, many theoretical and empirical results were presented showing the strength of bootstrap methods. As an illustration, Efron [@Efron1979], Hall [@Hall1986], Efron and Tibshirani[@EfronTibshi1986], and Hall [@Hall1988] showed that bootstrapping was at least as good if not better than existent methods, when the goal was to estimate the standard error of an estimator or find the confidence intervals of a parameter. Modifications were proposed to improve the algorithm in situations where the basic method was not producing accurate results. With the continuous improvement of computing power and speed, and the advantages of having ready-to-use statistical software for its implementation, the use of the bootstrap has become more and more popular in many fields.
As an illustration, if we are interested in the mean of the population, $\mu$, and we have collected one random sample, we can gain a large number of bootstrap samples from this original sample, use them to calculate sample means, order the sample means from smallest to largest, and choose the interval that contains the middle 95% of these sample means. This will be the simplest way to find a confidence interval based on the bootstrap. In the next few subsections, we explore how to incorporate this and similar methods to construct confidence intervals.
### Bootstrap samples: revisiting the almond activity {#sec-revisit-almond-bootstrap}
To study and understand the behavior of bootstrap samples, we return to our example of the chocolate-covered almonds in a bowl. Recall that the bowl is considered the population of almonds, and we are interested in estimating the population mean weight of almonds.
As we did before, we only have access to a single random sample. In this section, we use the data frame `almonds_sample_100`, a random sample of 100 almonds taken earlier. We call this the original sample, and it is used in this section to create the bootstrap samples.
The first 10 rows are shown:
```{r confidence-intervals-demo-code-v2-dup2}
almonds_sample_100
```
#### Constructing a bootstrap sample: resampling once {.unnumbered}
We start by constructing one bootstrap sample of `r num_almonds_sample` almonds from the original sample of `r num_almonds_sample` almonds. These are the steps needed to perform this task manually:
**Step 1**: Place the original sample of `r num_almonds_sample` almonds into a bag or hat.
**Step 2**: Mix the bag contents, draw one almond, weigh it, and record the weight as seen in @fig-confidence-intervals-tactile-resampling-alt.
```{r fig-confidence-intervals-tactile-resampling-alt, fig.alt="Photograph showing one almond being weighed at random as part of a tactile bootstrap resampling demonstration.", echo=FALSE, fig.cap="Step 2: Weighing one almond at random.", fig.show="hold", purl=FALSE, out.width="30%"}
include_graphics("images/sampling/almonds/one-almond.png")
```
**Step 3**: Put the almond back into the bag! In other words, replace it as seen in @fig-confidence-intervals-tactile-resampling-v4.
```{r fig-confidence-intervals-tactile-resampling-v4, fig.alt="Photograph showing the weighed almond being placed back into the hat (replacement step) before drawing the next bootstrap sample.", echo=FALSE, fig.cap="Step 3: Replacing almond.", fig.show="hold", purl=FALSE, out.width="50%"}
include_graphics("images/sampling/pennies/tactile_simulation/4_put_it_back.png")
```
**Step 4**: Repeat Steps 2 and 3 a total of `r num_almonds_sample - 1` more times, resulting in `r num_almonds_sample` weights.
These steps describe *resampling with replacement*\index{resampling}, and the resulting sample is called a *bootstrap sample*. This procedure results in some almonds being chosen more than once and other almonds not being chosen at all. Resampling with replacement induces *sampling variation*, so every bootstrap sample can be different than any other.
This activity can be performed manually following the steps described above. We can also take advantage of the R code we have introduced in @sec-sampling and do this virtually.
The data frame `almonds_sample_100` contains the random sample of almonds taken from the population. We show selected rows from this sample.
```{r confidence-intervals-create-almonds_sample_100}
almonds_sample_100 <- almonds_sample_100 |>
ungroup() |>
select(-replicate)
almonds_sample_100
```
We use `ungroup()` and `select` to eliminate the variable `replicate` from the `almonds_sample_100` as this variable may create clutter when resampling. We can now create a bootstrap sample also of size `r num_almonds_sample` by resampling with replacement once.
```{r confidence-intervals-virtual-sample, echo=-1}
set.seed(202)
boot_sample <- almonds_sample_100 |>
rep_sample_n(size = 100, replace = TRUE, reps = 1)
```
We have used this type of R syntax many times in @sec-sampling.
We first select the data frame `almonds_sample_100` that contains the almonds' weights in the original sample.
We then perform resampling with replacement once: we resample by using `rep_sample_n()`, a sample of size `r num_almonds_sample` by setting `size = 100`, with replacement by adding the argument `replace = TRUE`, and one time by setting `reps = 1`.
The object `boot_sample` is a bootstrap sample of `r num_almonds_sample` almonds' weights gained from the original sample of `r num_almonds_sample` almonds' weights. We show the first ten rows of `boot_sample`:
```{r confidence-intervals-v33}
boot_sample
```
We can also study some of the characteristics of this bootstrap sample, such as its sample mean:
```{r confidence-intervals-compute-mean-v6}
boot_sample |>
summarize(mean_weight = mean(weight))
```
```{r confidence-intervals-assign-resample_mean, echo=FALSE, purl=FALSE}
resample_mean <- boot_sample |>
summarize(mean_weight = mean(weight))
```
By using `summarize()` and `mean()` on the bootstrap sample `boot_sample`, we determine that the mean weight is `r resample_mean |> pull(mean_weight)` grams. Recall that the sample mean of the original sample was found in the previous subsection as `r x_bar`. So, the sample mean of the bootstrap sample is different than the sample mean of the original sample. This variation is induced by resampling with replacement, the method for finding the bootstrap sample. We can also compare the histogram of `weight`s for the bootstrap sample with the histogram of `weight`s for the original sample.
```{r confidence-intervals-hist, echo=TRUE, fig.show='hide'}
ggplot(boot_sample, aes(x = weight)) +
geom_histogram(binwidth = 0.1, color = "white") +
labs(title = "Resample of 100 weights")
ggplot(almonds_sample_100, aes(x = weight)) +
geom_histogram(binwidth = 0.1, color = "white") +
labs(title = "Original sample of 100 weights")
```
```{r fig-origandresample, fig.alt="Two side-by-side histograms of almond weights: the original sample (left) and one bootstrap resample drawn with replacement (right). Shapes are similar but not identical.", echo=FALSE, fig.cap="Comparing `weight` in the resampled `boot_sample` with the original sample `almonds_sample_100`.", purl=FALSE, fig.height=ifelse(knitr::is_latex_output(), 4.2, 4)}
p1 <- ggplot(boot_sample, aes(x = weight)) +
geom_histogram(binwidth = 0.1, color = "white") +
labs(title = "Resample of 100 almonds' weights") +
scale_x_continuous(limits = c(2.85, 4.15), breaks = seq(2.85, 4.15, 0.1)) +
scale_y_continuous(limits = c(0, 25), breaks = seq(0, 25, 5))# +
# theme(plot.margin = unit(c(1, 1, 1, 1), "cm"))
p2 <- ggplot(almonds_sample_100, aes(x = weight)) +
geom_histogram(binwidth = 0.1, color = "white") +
labs(title = "Original sample of 100 almonds' weights") +
scale_x_continuous(limits = c(2.85, 4.15), breaks = seq(2.85, 4.15, 0.1)) +
scale_y_continuous(limits = c(0, 25), breaks = seq(0, 25, 5))# +
# theme(plot.margin = unit(c(1, 1, 1, 1), "cm"))
p1 + p2 + plot_layout(ncol=1, guides = "collect")
```
Observe in @fig-origandresample that while the general shapes of both distributions of `weight`s are roughly similar, they are not identical.
This is the typical behavior of bootstrap samples. They are samples that have been determined from the original sample, but because replacement is used before each new observation is attained, some values often appear more than once while others often do not appear at all.
#### Many bootstrap samples: resampling multiple times {#sec-replicates .unnumbered}
In this subsection, we take full advantage of resampling with replacement by taking many bootstrap samples and study relevant information, such as the variability of their sample means. We can start by using the R syntax we used before, this time for `r n_manual_rep` replications.
```{r confidence-intervals-resample, echo= -1}
set.seed(20)
bootstrap_samples_35 <- almonds_sample_100 |>
rep_sample_n(size = 100, replace = TRUE, reps = 35)
bootstrap_samples_35
```
The syntax is the same as before, but this time we set `reps =` `r n_manual_rep` to get `r n_manual_rep` bootstrap samples.
The resulting data frame, `bootstrap_samples`, has `r n_manual_rep` $\cdot$ `r num_almonds_sample` = `r n_manual_rep * num_almonds_sample` rows corresponding to `r n_manual_rep` resamples of `r num_almonds_sample` almonds' weights. Let's now compute the resulting `r n_manual_rep` sample means using the same `dplyr` code as we did in the previous section:
```{r confidence-intervals-assign-boot_means}
boot_means <- bootstrap_samples_35 |>
summarize(mean_weight = mean(weight))
boot_means
```
Observe that `boot_means` has `r n_manual_rep` rows, corresponding to the `r n_manual_rep` bootstrap sample means. Furthermore, observe that the values of `mean_weight` vary as shown in @fig-resampling-35.