Menu

Confidence Intervals in R: t.test(), confint() and prop.test()

Get confidence intervals for means, proportions and model coefficients - t.test(), prop.test(), confint() - plus what "95% confident" actually means and how sample size drives the width.

This page includes runnable editors - edit, run, and see output instantly.

What "95% Confident" Actually Means

A confidence interval turns a point estimate ("the sample mean is 5.61") into an honest range ("the true mean is plausibly between 5.29 and 5.93"). But the phrase 95% confident is one of the most misread in statistics, so let's get it right up front.

The 95% describes the procedure, not the interval. Imagine rerunning your study over and over - new sample each time, new interval each time. The intervals would jump around, and about 95% of them would capture the true value; 5% would miss. Your one actual interval is a single draw from that process. What 95% does not mean: "there's a 95% probability the true mean is inside these numbers." The true mean is a fixed (unknown) number - it isn't wandering in and out of intervals; the intervals are what vary.

In practice the friendly reading is fine: the interval is the range of values compatible with your data. Just know which claim you're licensed to make when someone pushes.

CI for a Mean, the Easy Way

Every t.test() carries a confidence interval; you can run the test just to harvest it:

Mean 5.61, 95% CI roughly 5.29 to 5.93. The interval does the job a bare mean can't: it shows how much precision ten observations actually buy you.

The Same CI by Hand

The formula behind that interval is worth building once, because it demystifies every CI you'll ever read: estimate ± critical value × standard error.

Match it to the t.test() output - same interval to the last digit. Three moving parts:

  • The standard error sd(x)/sqrt(n) measures how much the sample mean wobbles (see descriptive statistics for the sd-vs-SE distinction).
  • qt(0.975, df) is the t critical value: for 95% coverage you leave 2.5% in each tail, hence 0.975. With df = 9 it's about 2.26 - fatter than the normal's 1.96, the small-sample tax for estimating the sd from the same data.
  • The margin of error is their product - the "±" number headlines quote.

Changing the Level: 90%, 99% and the Trade-Off

conf.level controls the coverage, and with it the width:

More confidence costs more width - a 99% interval must be wide enough to be right 99 times in 100, so it stretches; a 90% interval is tighter but misses twice as often as 95%. There's no free lunch, only a dial. 95% is pure convention: a default worth keeping unless you have a reason, not a law of nature.

CI for a Proportion: prop.test()

Suppose 47 of 120 surveyed users adopt a new feature. What's the plausible range for the true adoption rate?

Sample proportion 0.39, 95% CI roughly 0.30 to 0.49 - so "about 40% adoption" is honest only with that ±9-point halo attached. prop.test() uses a better approximation than the textbook p ± 1.96 × sqrt(p(1−p)/n) formula (it's a Wilson-type interval with continuity correction), which matters most near 0 or 1 - the textbook interval can poke outside [0, 1]; this one can't. For very small counts, binom.test(47, 120)$conf.int gives the exact version.

CIs for Model Coefficients: confint()

Fitted models get intervals through one generic function:

Each row brackets one coefficient of the linear regression: the wt slope's 95% interval runs from about −6.5 to −4.2 mpg per 1000 lbs. That's more informative than the summary's p-value - it says the effect is not just nonzero but at least ~4 mpg and possibly ~6.5.

For a logistic glm(), confint(fit) works the same but returns log-odds bounds; exponentiate to get odds-ratio intervals - exp(confint(fit)) - and remember the "no effect" reference value becomes 1 instead of 0.

Sample Size: the Square-Root Law

Width shrinks with sqrt(n), which has a memorable consequence: quadruple the data, halve the interval. Watch it happen with simulated data - same distribution, one sample 4× the size (seeding makes this reproducible; see random numbers):

The widths land close to a 2:1 ratio (sampling noise keeps it from being exact). The square root is why precision gets expensive: the first 100 observations buy you more narrowing than the next 300 combined, and halving an already-narrow interval always costs 4× whatever you paid so far.

CI and P-Value: Two Views of One Test

A confidence interval and a hypothesis test are the same information in different clothes. The 95% CI contains exactly the parameter values that a two-sided test at the 0.05 level would fail to reject. So:

  • CI for a mean difference excludes 0 ⇔ the t-test says p < 0.05.
  • CI for an odds ratio excludes 1 ⇔ the coefficient's p < 0.05.

When you have the interval, you usually have the better summary: it delivers the same significance verdict plus the size of the effect in real units. "p = 0.03" says a difference exists; "95% CI: 0.2 to 7.6" says it exists and might be trivial or might be huge - which is often the finding that matters.

What You Take Away

  • 95% describes the procedure's long-run hit rate, not the probability this one interval caught the truth.
  • Mean: t.test(x)$conf.int, or by hand as mean ± qt(0.975, n−1) × SE.
  • Proportion: prop.test(x, n)$conf.int; model coefficients: confint(fit) (exponentiate for glm odds ratios).
  • Higher confidence = wider interval; 95% is convention, not law.
  • Width shrinks with sqrt(n): 4× the data halves the interval.
  • The CI contains every value a 0.05-level test wouldn't reject - and unlike the p-value, it shows effect size.

Next up: the simulation toolkit behind all of this - random numbers with rnorm, runif, sample and set.seed.

Frequently Asked Questions

How do you calculate a 95% confidence interval in R?

For a mean, the quickest route is t.test(x)$conf.int. For a proportion, prop.test(successes, trials)$conf.int. For the coefficients of a fitted lm() or glm() model, confint(fit). All three default to 95%; change it with conf.level = 0.90 (or 0.99).

What does a 95% confidence interval actually mean?

It's a statement about the procedure: if you repeated the study many times and built an interval each time, about 95% of those intervals would contain the true value. It is not "a 95% probability the parameter is inside this particular interval" - the parameter is a fixed number, and any single interval either caught it or didn't.

How do you compute a confidence interval by hand in R?

Mean ± critical value × standard error. For a mean: m <- mean(x); se <- sd(x)/sqrt(length(x)); m + c(-1, 1) * qt(0.975, df = length(x) - 1) * se. The qt(0.975, df) call is the t critical value that leaves 2.5% in each tail.

How does sample size affect a confidence interval?

Width shrinks with the square root of n: quadruple the sample and the interval halves. That square root is why the last bit of precision is expensive - going from ±2 to ±1 costs four times the data, not two.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED