Skip to content

09-02: Exercises — Confidence Interval for a Proportion

Notes reference: 09-02: Confidence Interval for a Proportion


Q1: Basic proportion interval

In a random sample of 800 adults, 344 say they exercise at least three times a week.

Build a 95% confidence interval for the population proportion.

Solution

p̂ = 344/800 = 0.43        q̂ = 0.57

CHECK:  n p̂ = 344 ≥ 5   ✓      n q̂ = 456 ≥ 5   ✓

SE = √(0.43 × 0.57 / 800) = √(0.2451/800) = √0.000306375 = 0.017504

z  = 1.96
E  = 1.96 × 0.017504 = 0.034308        →  ±3.4 percentage points

CI = 0.43 ± 0.0343  =  (0.3957, 0.4643)   →  (39.6%, 46.4%)
INTERPRETATION
"We are 95% confident that between 39.6% and 46.4% of all adults in
this population exercise at least three times a week."

Note the interval lies entirely BELOW 0.50, so we can also say the
evidence is against a majority exercising this often.
=344/800                                        ' 0.43
=SQRT(0.43*0.57/800)                            ' 0.017504
=NORM.S.INV(0.975)*SQRT(0.43*0.57/800)          ' 0.034308
=0.43-0.034308  &  " to "  &  0.43+0.034308
prop.test(344, 800, correct = FALSE)$conf.int    # Wilson: 0.3963 0.4643
binom.test(344, 800)$conf.int                    # exact:  0.3954 0.4652
from statsmodels.stats.proportion import proportion_confint
proportion_confint(344, 800, method="normal")    # Wald
proportion_confint(344, 800, method="wilson")

Q2: Three confidence levels

Using the Q1 data, build 90%, 95%, and 99% intervals.

Solution

SE = 0.017504

90%:  z = 1.6449   E = 0.02879   →  (0.4012, 0.4588)   width 0.0576
95%:  z = 1.9600   E = 0.03431   →  (0.3957, 0.4643)   width 0.0686
99%:  z = 2.5758   E = 0.04509   →  (0.3849, 0.4751)   width 0.0902

All three intervals lie entirely below 0.50 — the conclusion "fewer than half exercise this often" is robust to the confidence level chosen.


Q3: Sample size, no prior estimate

A pollster wants a margin of error of 2.5 percentage points at 95% confidence, with no prior information about p.

  1. Required n
  2. Required n if a previous poll suggested p ≈ 0.62
  3. Required n for E = 0.01 with no prior

Solution

              ( z )²
n  =  p̂ q̂ ·  ( ─── )         ALWAYS round UP
              ( E )

1.  No prior  →  use p̂ = 0.5 (the most conservative choice, since p̂q̂
    is maximized at 0.25):
        n = 0.25 × (1.96/0.025)² = 0.25 × 6146.56 = 1536.64  →  n = 1537

2.  With p̂ = 0.62:  p̂q̂ = 0.62 × 0.38 = 0.2356
        n = 0.2356 × 6146.56 = 1448.13                       →  n = 1449
    The prior estimate saves 88 respondents.

3.  E = 0.01, no prior:
        n = 0.25 × (1.96/0.01)² = 0.25 × 38416 = 9604         →  n = 9604
    Going from ±2.5% to ±1% costs 6× the sample.
=ROUNDUP(0.25*(NORM.S.INV(0.975)/0.025)^2, 0)          ' 1537
=ROUNDUP(0.62*0.38*(NORM.S.INV(0.975)/0.025)^2, 0)     ' 1449
=ROUNDUP(0.25*(NORM.S.INV(0.975)/0.01)^2, 0)           ' 9604
n_prop <- function(E, p = 0.5, conf = 0.95)
  ceiling(p*(1-p) * (qnorm(1-(1-conf)/2)/E)^2)
n_prop(0.025); n_prop(0.025, 0.62); n_prop(0.01)

Q4: Why polls use ~1,000 people

Show that a national poll of 1,000 gives roughly a ±3% margin of error, and explain why the country's population size is irrelevant.

Solution

Worst case p̂ = 0.5:

E = 1.96 × √(0.5 × 0.5 / 1000) = 1.96 × √0.00025 = 1.96 × 0.0158114
  = 0.030990                              →  ±3.1 percentage points

WHY POPULATION SIZE DOES NOT MATTER

The formula   E = z√(p̂q̂/n)   contains NO N.

The finite population correction  √((N − n)/(N − 1))  only matters when
n exceeds about 5% of N:

    N = 30,000,  n = 1000  →  FPC = √(29000/29999) = 0.9832   (1.7% narrower)
    N = 300 million, n = 1000 → FPC = 0.999998                (negligible)

So the same 1,000 respondents give essentially the same precision for a
town of 30,000 as for a country of 300 million. What matters is the SAMPLE
size, not the fraction of the population sampled.

Q5: A troublesome small sample

In a sample of 20 items, 1 is defective. Build a 95% CI for the defect rate three ways: Wald, plus-four, and exact.

Solution

p̂ = 1/20 = 0.05

CONDITION CHECK:  n p̂ = 1  <  5   ✗
The Wald interval is NOT reliable here — but compute it anyway to see why.

WALD
    SE = √(0.05 × 0.95 / 20) = √0.002375 = 0.048734
    E  = 1.96 × 0.048734 = 0.095519
    CI = 0.05 ± 0.0955 = (−0.0455, 0.1455)
                          ↑ A NEGATIVE PROBABILITY. The method has failed.

PLUS-FOUR (Agresti-Coull)
    p̃ = (1 + 2)/(20 + 4) = 3/24 = 0.125
    SE = √(0.125 × 0.875 / 24) = √0.0045573 = 0.067508
    E  = 1.96 × 0.067508 = 0.132316
    CI = 0.125 ± 0.1323 = (−0.0073, 0.2573)   →  truncate to (0, 0.257)

EXACT (Clopper-Pearson)
    CI = (0.00126, 0.24871)     — always inside [0, 1] by construction

RECOMMENDATION: with np̂ < 5, report the EXACT (or Wilson) interval and
say which method you used.
binom.test(1, 20)$conf.int                       # 0.00126 0.24871
prop.test(1, 20, correct = FALSE)$conf.int       # Wilson: 0.00890 0.23610
from statsmodels.stats.proportion import proportion_confint
proportion_confint(1, 20, method="beta")         # exact
proportion_confint(1, 20, method="wilson")
proportion_confint(1, 20, method="agresti_coull")

Q6: Difference of two proportions

A drug trial: 45 of 150 in the treatment group improved; 30 of 150 in the control group improved.

Build a 95% CI for p₁ − p₂.

Solution

p̂₁ = 45/150 = 0.30        p̂₂ = 30/150 = 0.20

Point estimate:  p̂₁ − p̂₂ = 0.10       (10 percentage points)

                 ______________________
                /  p̂₁q̂₁     p̂₂q̂₂
SE  =        √   ────── + ──────
                    n₁        n₂

    = √(0.30 × 0.70/150  +  0.20 × 0.80/150)
    = √(0.0014 + 0.0010667)
    = √0.0024667
    = 0.049666

E   = 1.96 × 0.049666 = 0.097345

CI  = 0.10 ± 0.0973  =  (0.0027, 0.1973)   →  (0.3%, 19.7%)
INTERPRETATION
The interval EXCLUDES 0 (just barely), so the treatment's improvement
rate is significantly higher at the 5% level.

But look at the width: the true advantage could be as little as 0.3
percentage points or as much as 19.7. That is a huge range — the study
is under-powered. A larger trial would be needed before making any
clinical claim.
=45/150-30/150                                          ' 0.10
=SQRT(0.3*0.7/150 + 0.2*0.8/150)                        ' 0.049666
=0.10-NORM.S.INV(0.975)*0.049666                        ' 0.002655
=0.10+NORM.S.INV(0.975)*0.049666                        ' 0.197345
prop.test(c(45, 30), c(150, 150), correct = FALSE)$conf.int
# 0.00266 0.19734
from statsmodels.stats.proportion import confint_proportions_2indep
confint_proportions_2indep(45, 150, 30, 150, method="wald")

Q7: Read a news report critically

A headline reads: "58% of Americans support the policy — poll of 1,004 adults, margin of error ±3%."

  1. Give the 95% confidence interval.
  2. Can the outlet claim "a majority supports the policy"?
  3. Name three sources of error the ±3% does not cover.

Solution

1.  58% ± 3%  =  (55%, 61%)

    Verify: E = 1.96 × √(0.58 × 0.42/1004) = 1.96 × 0.015575 = 0.030527  ✓

2.  YES — the ENTIRE interval lies above 50%, so a majority is supported
    at the 95% confidence level.

    Contrast: if the poll had found 51% ± 3%, the interval (48%, 54%)
    would straddle 50% and the "majority" claim would NOT be justified.
    That situation is usually reported as "a statistical tie".

3.  THE MARGIN OF ERROR COVERS ONLY SAMPLING VARIABILITY. It does not
    cover:
      • NONRESPONSE BIAS — modern phone polls answer rates are often <10%
      • COVERAGE BIAS    — who is in the calling frame at all
      • QUESTION WORDING — "support the policy" vs. "support the
                           controversial policy" can move results 10 points
      • HOUSE EFFECTS    — weighting and likely-voter models differ by pollster
      • TIMING           — opinion moves; the poll is a snapshot

    A ±3% margin with a 7% response rate is precision theatre.

Q8: Verify the coverage claim

Show by simulation that a 95% Wald interval really does capture the true p about 95% of the time when n is large — and rather less often when n is small.

Solution

set.seed(11)

coverage <- function(n, p, reps = 20000, conf = 0.95) {
  z <- qnorm(1 - (1 - conf)/2)
  x <- rbinom(reps, n, p)
  ph <- x / n
  e  <- z * sqrt(ph * (1 - ph) / n)
  mean(ph - e <= p & p <= ph + e)
}

data.frame(
  n        = c(20, 20, 100, 100, 1000),
  p        = c(0.50, 0.05, 0.50, 0.05, 0.50),
  coverage = mapply(coverage, c(20, 20, 100, 100, 1000),
                              c(0.50, 0.05, 0.50, 0.05, 0.50))
)
TYPICAL OUTPUT

     n     p    coverage
    20  0.50     0.959
    20  0.05     0.641      ← disastrously below the promised 95%
   100  0.50     0.943
   100  0.05     0.876      ← still short
  1000  0.50     0.951

CONCLUSION
The Wald interval delivers its promised coverage when n is large AND p
is near 0.5. When p is near 0 or 1, it under-covers badly — sometimes
catastrophically. That is precisely why R's prop.test and Python's
statsmodels default to the WILSON interval instead.

Rerun the simulation with method = "wilson" and the coverage stays
near 0.95 in every row.
rng = np.random.default_rng(11)

def coverage(n, p, reps=20000, conf=0.95):
    z = stats.norm.ppf(1 - (1 - conf) / 2)
    ph = rng.binomial(n, p, reps) / n
    e = z * np.sqrt(ph * (1 - ph) / n)
    return np.mean((ph - e <= p) & (p <= ph + e))

for n, p in [(20, .5), (20, .05), (100, .5), (100, .05), (1000, .5)]:
    print(n, p, round(coverage(n, p), 3))

⬅️ Previous: 09-01: Exercises — Confidence Interval for a Mean ➡️ Next: 10-01: Exercises — Hypothesis Testing Fundamentals