Section 1 of 10

1 Before you start

Before you begin, take a few minutes to check what you already know and how confident you feel. You will see the same questions again at the end of the module — this helps both you and us measure what you have learned. Click an option for every question and confidence rating, then click Next to continue.

Pre-test

You have eight HbA1c readings in a vector and want a 95% confidence interval for the mean. Which line gives it to you directly?

Pre-test

A rough 95% confidence interval for a mean is the estimate give or take about how many standard errors?

Pre-test

Why does t.test() give a slightly wider interval than the by-hand estimate mean(x) + c(-1.96, 1.96) * se for a small sample?

Pre-test

A study reports mean HbA1c 7.8, 95% CI [7.2, 8.4]. Which statement is the correct interpretation of the 95%?

Pre-test

In a clinic, 38 of 200 patients reached their HbA1c target. Which call returns a 95% confidence interval for that proportion?

Pre-test

You have only 4 events out of 30 patients and want a confidence interval for the proportion. Which function is the safer choice for such small counts?

Pre-test

Length of stay is strongly right-skewed and you want a 95% confidence interval for its median. Which approach fits?

Pre-test

You built a bootstrap distribution of medians in boot_meds. Which line reads off the 95% confidence interval?

Pre-confidence

I can build a 95% confidence interval for a mean in R with t.test(), read it off with $conf.int, and state correctly that the 95% refers to the procedure across many studies rather than the one interval.

Not at all confident
Fully confident
Pre-confidence

I can build a confidence interval for a proportion with prop.test() or the exact binom.test(), and choose binom.test() when the event count is small.

Not at all confident
Fully confident
Pre-confidence

I can bootstrap a 95% confidence interval for a skewed median with sample(replace = TRUE), replicate(), and quantile(), and report any estimate as "estimate, 95% CI [low, high]".

Not at all confident
Fully confident
Section 2 of 10

2 Introduction

In Part I you saw the Central Limit Theorem make the sample mean bell-shaped, and you learned that the standard error measures how much that mean would wobble if you ran the study again. This part cashes that in: it turns a single estimate into a confidence interval — a stated range of plausible values for the population truth you could not measure directly.

This part of the module covers five skills — building each interval in R, plus reading what it means and reporting it cleanly:

  • A confidence interval for a mean — build it once by hand as the estimate give or take 1.96 standard errors, then let t.test() do it properly, and read the range off with $conf.int.
  • What the 95% really means — a property of the procedure across many repeated studies, not a probability for the one interval on your screen.
  • Intervals for a proportion — a large-sample interval with prop.test() and the exact binom.test() you reach for when the event count is small.
  • A skewed median by bootstrap — resample your own data with sample(x, replace = TRUE), recompute the median many times, and read the middle 95% off with quantile() — no formula required.
  • Reporting the result — in one consistent shape, "estimate, 95% CI [low, high]", pulling the numbers cleanly with broom::tidy() rather than copying them by hand.

By the end of this part you will be able to build a 95% confidence interval for a mean, a proportion, and a skewed median in R, state correctly what the 95% refers to, and report any estimate as "estimate, 95% CI [low, high]".

Try every snippet in the R Scratchpad on the right. The dataset diabetes_clinic.csv is already loaded, and the small vectors and bootstrap simulations build their own data with c(), set.seed(), and replicate(), so you can run everything as you read.

Section 3 of 10

3 A 95% confidence interval for a mean

The CLT lets us go from a point estimate to a range. A confidence interval is a range of plausible values for the population parameter, built from your sample so that the procedure traps the true value 95% of the time. For a mean, R hands you the whole interval through t.test().

A confidence interval is a procedure, not a statement about one interval; repeat it across many samples and about 95% of the intervals will contain the one fixed true mean.
A confidence interval is a procedure, not a statement about one interval; repeat it across many samples and about 95% of the intervals will contain the one fixed true mean.

You already have the pieces. A rough 95% interval is the estimate give or take about 1.96 standard errors — that 1.96 is the qnorm(0.975) cut-off from the Normal curve in Part I. Build it by hand once, then let t.test() do it properly (it uses the slightly wider t-distribution for small samples).

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
hba1c <- c(7.2, 8.1, 6.5, 9.4, 7.8, 6.9, 8.4, 7.1)
se <- sd(hba1c) / sqrt(length(hba1c))
mean(hba1c) + c(-1.96, 1.96) * se
A 95% confidence interval is just your estimate reaching out 1.96 standard errors on each side, and the t-distribution stretches that reach a little further when the sample is small.
A 95% confidence interval is just your estimate reaching out 1.96 standard errors on each side, and the t-distribution stretches that reach a little further when the sample is small.

You do not need the t-distribution algebra. Call t.test on your vector and read the confidence interval off the result, or pull it out cleanly with $conf.int.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
hba1c <- c(7.2, 8.1, 6.5, 9.4, 7.8, 6.9, 8.4, 7.1)
t.test(hba1c)
t.test(hba1c)$conf.int
t.test() returns a named list holding the whole result, and $conf.int selects just the confidence interval from it, so no t-distribution formula is needed.
t.test() returns a named list holding the whole result, and $conf.int selects just the confidence interval from it, so no t-distribution formula is needed.

Now the interpretation that examiners and reviewers care about most. The 95% describes the long-run behaviour of the procedure, not a probability for this one interval. If you repeated the whole study many times and built an interval each time, about 95% of those intervals would contain the true mean.

Say it the wrong way and you have made the most famous error in statistics. It is wrong to say "there is a 95% probability the true mean lies in this interval." The true mean is a fixed number; your specific interval either caught it or did not. The 95% is a property of the method across many studies, not of the single interval on your screen.

A 95% confidence interval is a verdict from a procedure that captures the fixed true mean in about 95 of every 100 studies, so any single interval has already either caught the mean or missed it rather than holding a 95% chance of containing it.
A 95% confidence interval is a verdict from a procedure that captures the fixed true mean in about 95 of every 100 studies, so any single interval has already either caught the mean or missed it rather than holding a 95% chance of containing it.

A wider interval means more uncertainty. Intervals shrink as the sample grows, for the same square-root reason the SE shrinks. And never report a bare point estimate with no interval — a mean of 7.8 alone hides whether the truth could plausibly be 7.2 or 8.4, which changes the clinical story entirely.

A point estimate is only half the story; the interval around it shows how much the true value could plausibly vary, and that uncertainty narrows in proportion to the square root of the sample size.
A point estimate is only half the story; the interval around it shows how much the true value could plausibly vary, and that uncertainty narrows in proportion to the square root of the sample size.
Section 4 of 10

4 Intervals for a proportion and for a skewed median

Means are not the only estimates that need an interval. Proportions and medians do too, and R has a clean function for each. This section finishes your toolkit.

Section 4.1 of 10

4.1 A proportion with prop.test() or binom.test()

Suppose 38 of 200 patients reached their HbA1c target. The sample proportion is 0.19, but you owe the reader an interval. prop.test gives a large-sample interval; binom.test gives an exact one, which you prefer when counts are small.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
prop.test(38, 200)
binom.test(38, 200)
A single proportion is only half the answer; you report an interval around it, and while the large-sample and exact methods agree when the sample is big, small counts make the interval wide and the exact one the safer choice.
A single proportion is only half the answer; you report an interval around it, and while the large-sample and exact methods agree when the sample is big, small counts make the interval wide and the exact one the safer choice.

Read the interval the same procedural way as the mean: the method, repeated across many studies, would trap the true proportion 95% of the time. Reach for the exact binom.test() when you have only a handful of events, where the large-sample approximation gets shaky.

Section 4.2 of 10

4.2 A skewed median by bootstrap

What if you want an interval for a median from skewed data, where no neat formula applies? You bootstrap it: resample your own data with replacement many times, recompute the median each time, and read the middle 95% of those medians as your interval.

IMAGE GIF_bootstrap_median

A median's confidence interval can be read straight off your own data by resampling it with replacement many times and keeping the middle 95% of the resulting medians, no formula required.

The building blocks are familiar. sample(x, replace = TRUE) draws a resample the same size as x; replicate() repeats it; quantile with c(0.025, 0.975) cuts off the lowest and highest 2.5% to leave the central 95%.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
set.seed(2025)
los <- rexp(120, rate = 1 / 5)
boot_meds <- replicate(2000, median(sample(los, replace = TRUE)))
quantile(boot_meds, c(0.025, 0.975))
A confidence interval for any statistic can be built from your own data alone, by resampling it with replacement many times, recomputing the statistic each time, and keeping the middle 95% of those values, with no formula or distributional assumption required.
A confidence interval for any statistic can be built from your own data alone, by resampling it with replacement many times, recomputing the statistic each time, and keeping the middle 95% of those values, with no formula or distributional assumption required.

The two numbers you get back are the lower and upper limits of a 95% bootstrap confidence interval for the median. The same set.seed() habit applies — fix it so the interval is reproducible.

Section 4.3 of 10

4.3 Report it: estimate, 95% CI [low, high]

However you got the interval, report it in one consistent shape: the point estimate, then "95% CI", then the low and high in square brackets — for example, "mean HbA1c 7.8, 95% CI [7.2, 8.4]". The estimate tells the reader your best guess; the interval tells them how sure to be.

A reported result pairs one best-guess value with an interval of plausible values around it, and the convention is to write them in a fixed order: the estimate, then 95% CI, then [low, high].
A reported result pairs one best-guess value with an interval of plausible values around it, and the convention is to write them in a fixed order: the estimate, then 95% CI, then [low, high].

Pull the numbers programmatically rather than copying by hand. tidy from the broom package turns any t.test() or prop.test() result into a tidy one-row table with estimate, conf.low, and conf.high columns you can read or drop straight into a report.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
library(broom)
hba1c <- c(7.2, 8.1, 6.5, 9.4, 7.8, 6.9, 8.4, 7.1)
tidy(t.test(hba1c))
broom::tidy() repackages a verbose t.test() result into a single labelled row, so the estimate and its confidence interval can be read or pasted into a report directly instead of parsed out of console text by hand.
broom::tidy() repackages a verbose t.test() result into a single labelled row, so the estimate and its confidence interval can be read or pasted into a report directly instead of parsed out of console text by hand.
Section 5 of 10

5 Put it together

The worked example below fades its support: first study a full solution, then fill the gap, then solve a fresh one on your own. It estimates a mean with a t.test interval and recomputes the standard error by hand.

Worked example · Estimate a mean with its 95% CI and a hand SE

Work through this example in three stages. You unlock each stage only after the tutor confirms the previous one. Each stage removes more of the scaffolding — by the end you are writing it yourself.

Problem: A small cohort had these systolic blood pressures (mmHg): 132, 145, 128, 151, 139, 136. Report the mean with its 95% confidence interval, then recompute the standard error of the mean by hand.

Stage 1 · Study the solved example
Fully solved solution
sbp <- c(132, 145, 128, 151, 139, 136)
t.test(sbp)$conf.int
sd(sbp) / sqrt(length(sbp))
Walk-through
  1. Store the six readings in a vector with c()
  2. t.test(sbp)$conf.int gives the 95% confidence interval for the mean
  3. the standard error is the SD divided by the square root of the sample size, sd(sbp) / sqrt(length(sbp))
Section 6 of 10

6 Check your understanding

You have reached the end of the module. Try the same questions again — your answers here, paired with your pre-test answers, are how we measure what the module taught you. Answer every question and confidence rating, then click Submit and see results to view your score.

Post-test

You have eight HbA1c readings in a vector and want a 95% confidence interval for the mean. Which line gives it to you directly?

Post-test

A rough 95% confidence interval for a mean is the estimate give or take about how many standard errors?

Post-test

Why does t.test() give a slightly wider interval than the by-hand estimate mean(x) + c(-1.96, 1.96) * se for a small sample?

Post-test

A study reports mean HbA1c 7.8, 95% CI [7.2, 8.4]. Which statement is the correct interpretation of the 95%?

Post-test

In a clinic, 38 of 200 patients reached their HbA1c target. Which call returns a 95% confidence interval for that proportion?

Post-test

You have only 4 events out of 30 patients and want a confidence interval for the proportion. Which function is the safer choice for such small counts?

Post-test

Length of stay is strongly right-skewed and you want a 95% confidence interval for its median. Which approach fits?

Post-test

You built a bootstrap distribution of medians in boot_meds. Which line reads off the 95% confidence interval?

Post-confidence

I can build a 95% confidence interval for a mean in R with t.test(), read it off with $conf.int, and state correctly that the 95% refers to the procedure across many studies rather than the one interval.

Not at all confident
Fully confident
Post-confidence

I can build a confidence interval for a proportion with prop.test() or the exact binom.test(), and choose binom.test() when the event count is small.

Not at all confident
Fully confident
Post-confidence

I can bootstrap a 95% confidence interval for a skewed median with sample(replace = TRUE), replicate(), and quantile(), and report any estimate as "estimate, 95% CI [low, high]".

Not at all confident
Fully confident
Section 7 of 10

7 Your results

Here is how your post-test answers compare with your pre-test answers. The pre/post pairing is the most reliable way to see what this module actually taught you.

Your score

Submit the post-test to see your results.

Muddiest point

What is the one thing from this module that is still unclear to you?

Rate this module

Overall, how would you rate this module?

How likely are you to recommend this module to a peer? (0 = not at all, 10 = extremely likely)