Population Proportion
A population proportion is a parameter: the fraction of a whole population that has some characteristic. It is written without a hat, because it is not an estimate of anything — it is the thing being estimated.
\[ p = \frac{X}{N} \]
- \(X\) — the number of individuals in the population with the characteristic
- \(N\) — the size of the whole population
A university has 10,000 students and 6,000 of them are undergraduates, so \(p = 6000/10000 = 0.6\). When the whole population cannot be measured, a sample proportion \(\hat{p} = x/n\) is used to estimate it: survey 200 students, find 120 undergraduates, and \(\hat{p} = 0.6\).
The standard interval follows. With \(\hat{p} = 0.6\) and \(n = 200\), the margin of error is \(1.96\sqrt{0.6 \times 0.4 / 200} \approx 0.068\), giving \(0.6 \pm 0.068 = (0.532, 0.668)\). That interval is fine. What is worth noticing is that the formula never used \(N\) — and the definition of \(p\) is built on \(N\).
The formula assumes a population you do not have
\(\sqrt{\hat{p}(1-\hat{p})/n}\) is the standard error for sampling with replacement, or equivalently from an infinite population. Real surveys do not put a respondent back in the pool and risk asking them again. When you sample without replacement from a population of size \(N\), each observation removes some of what was left to learn, and the standard error shrinks by the finite-population correction \(\sqrt{(N-n)/(N-1)}\).
import numpy as np
from scipy.stats import hypergeom, norm
z = norm.ppf(0.975)
N, p = 10_000, 0.6
X = int(round(p * N))
"""A population proportion is defined over a finite population of N.
The usual standard error is not - it assumes an infinite one."""
print(f" a university of N = {N:,} students, {X:,} of them undergraduates (p = {p})")
print(f"{'sample n':>10}{'textbook SE':>14}{'finite-population SE':>23}{'ratio':>8}{'half-width':>13}")
for n in (200, 1000, 2500, 5000, 9000, 10_000):
se = np.sqrt(p * (1 - p) / n)
fpc = np.sqrt((N - n) / (N - 1))
print(f"{n:>10,}{se:>14.6f}{se * fpc:>23.6f}{fpc:>8.4f}{z * se * fpc:>13.6f}")
n = N
se = np.sqrt(p * (1 - p) / n)
print(f" textbook p-hat = {p:.4f} +/- {z * se:.6f}")
print(f" with the correction p-hat = {p:.4f} +/- {z * se * np.sqrt((N - n) / (N - 1)):.6f}")
def coverage(n, corrected):
k = np.arange(min(n, X) + 1)
ph = k / n
se = np.sqrt(ph * (1 - ph) / n)
if corrected:
se = se * np.sqrt((N - n) / (N - 1))
return float(hypergeom.pmf(k, N, X, n) @ ((ph - z * se <= p) & (p <= ph + z * se)))
"""Sampling without replacement from a finite population is hypergeometric,
so coverage is enumerated exactly rather than simulated."""
print(f"{'sample n':>10}{'textbook':>12}{'corrected':>12}")
for n in (200, 1000, 2500, 5000, 9000):
print(f"{n:>10,}{coverage(n, False):>12.4f}{coverage(n, True):>12.4f}")
# a university of N = 10,000 students, 6,000 of them undergraduates (p = 0.6)
# sample n textbook SE finite-population SE ratio half-width
# 200 0.034641 0.034295 0.9900 0.067216
# 1,000 0.015492 0.014698 0.9487 0.028807
# 2,500 0.009798 0.008486 0.8661 0.016632
# 5,000 0.006928 0.004899 0.7071 0.009602
# 9,000 0.005164 0.001633 0.3162 0.003201
# 10,000 0.004899 0.000000 0.0000 0.000000
# textbook p-hat = 0.6000 +/- 0.009602
# with the correction p-hat = 0.6000 +/- 0.000000
# sample n textbook corrected
# 200 0.9513 0.9416
# 1,000 0.9587 0.9515
# 2,500 0.9763 0.9496
# 5,000 0.9945 0.9499
# 9,000 1.0000 0.9476
When it matters, and when to forget it
The practical rule reads straight off the table: the correction matters once the sample is a noticeable fraction of the population. At \(n/N = 0.02\) it is 0.99 and not worth mentioning. At \(n/N = 0.5\) the uncorrected interval is 41% wider than it needs to be, and at \(n/N = 0.9\) it is more than three times too wide. The usual cut-off of 5% of the population is a reasonable place to start caring.
Omitting the finite-population correction makes this interval wider than the otherwise identical corrected interval. That relative width does not guarantee at least nominal coverage: the Wald approximation can still under-cover at rare rates or small samples. Choose an interval appropriate to the sampling design, then account for sampling without replacement. This matters especially for small internal populations sampled heavily.
Most public polling is the other case. A national survey of 1,200 people from a population of 40 million has a correction of 0.999985, and the reported margin of error is right to ignore it. That is the source of the fact that sounds wrong but is not: for a fixed level of precision, a survey of a city needs almost exactly as many respondents as a survey of a country.
The harder problem is the frame, not the formula
A population proportion is only defined once the population is. “The proportion of our users who are active” requires a decision about whether a user who signed up and never returned is in \(N\), and moving them in or out changes \(p\) without changing anything about the world. The correction above is arithmetic; this is a definition, and it has to be written down before the estimate means anything.
Nor does either fix a sample that does not represent the frame. Selection and nonresponse bias shift \(\hat{p}\) away from \(p\) by an amount that no standard error describes, and a large \(n\) makes the interval narrower around the wrong value. The finite-population correction assumes the sample was drawn at random from the \(N\); once that fails, it is correcting the smaller of two errors.
References
- SciPy documentation,
scipy.stats.hypergeomandscipy.stats.norm. docs.scipy.org
Discover more from Insightful Data Lab
Subscribe to get the latest posts sent to your email.
