One-Proportion Z-Test — Testing Population Proportions

Hypothesis TestingParametric TestsFree Lesson

Advertisement

One-Proportion Z-Test

Tests whether a population proportion π equals a hypothesized value π₀.

z=p^π0π0(1π0)/nz = \frac{\hat{p} - \pi_0}{\sqrt{\pi_0(1-\pi_0)/n}}


Conditions for Validity

The test assumes the sampling distribution of p̂ is approximately normal:

  • nπ₀ ≥ 10 and n(1−π₀) ≥ 10
  • Random sample from the population
  • Independence (sampling without replacement: n < 10% of N)
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

def proportion_z_test(successes, n, pi_0, alternative='two-sided', alpha=0.05):
    p_hat = successes / n
    
    # Check conditions
    if n * pi_0 < 10 or n * (1 - pi_0) < 10:
        print("WARNING: Conditions not met (nπ₀ or n(1-π₀) < 10). Use exact binomial test.")
    
    # Test statistic
    se = np.sqrt(pi_0 * (1 - pi_0) / n)
    z = (p_hat - pi_0) / se
    
    # P-value
    if alternative == 'two-sided':
        p_val = 2 * stats.norm.sf(abs(z))
    elif alternative == 'less':
        p_val = stats.norm.cdf(z)
    elif alternative == 'greater':
        p_val = stats.norm.sf(z)
    
    # Confidence interval (Wilson interval — more accurate)
    z_crit = stats.norm.ppf(1 - alpha/2)
    # Standard CI
    se_ci = np.sqrt(p_hat * (1 - p_hat) / n)
    ci_std = (p_hat - z_crit * se_ci, p_hat + z_crit * se_ci)
    
    # Effect size (Cohen's h)
    h = 2 * np.arcsin(np.sqrt(p_hat)) - 2 * np.arcsin(np.sqrt(pi_0))
    
    print(f"=== One-Proportion Z-Test ===")
    print(f"H₀: π = {pi_0}")
    print(f"H₁: π {'≠' if alternative=='two-sided' else '<' if alternative=='less' else '>'} {pi_0}")
    print(f"\np̂ = {successes}/{n} = {p_hat:.4f}")
    print(f"z = {z:.4f}")
    print(f"p-value = {p_val:.6f}")
    print(f"95% CI (standard): ({ci_std[0]:.4f}, {ci_std[1]:.4f})")
    print(f"Cohen's h = {h:.4f}")
    print(f"Decision: {'Reject H₀' if p_val < alpha else 'Fail to reject H₀'}")
    return z, p_val

# Example 1: Is a coin fair?
print("=== Example 1: Coin Fairness Test ===")
# 63 heads in 100 flips. Is coin biased?
proportion_z_test(63, 100, 0.50, alternative='two-sided')

# Example 2: Website conversion rate
print("\n=== Example 2: Website Conversion Rate ===")
# Claim: 5% conversion rate. We observe 23 conversions in 350 visitors.
proportion_z_test(23, 350, 0.05, alternative='greater')

Comparison: Z-Test vs Exact Binomial

from scipy.stats import binom_test

# Small sample: when Z approximation breaks down
successes, n, pi_0 = 8, 20, 0.5

# Z-test (may be inaccurate for small n)
se = np.sqrt(pi_0 * (1 - pi_0) / n)
z = (successes/n - pi_0) / se
p_z = 2 * stats.norm.sf(abs(z))

# Exact binomial test (always valid)
p_exact = binom_test(successes, n, pi_0, alternative='two-sided')

print(f"n={n}, x={successes}, π₀={pi_0}")
print(f"Z-test p-value: {p_z:.6f}")
print(f"Exact binomial p-value: {p_exact:.6f}")
print(f"Difference: {abs(p_z - p_exact):.6f}")
print("Use exact binomial when nπ₀ < 10 or n(1-π₀) < 10")

Key Takeaways

  1. Conditions: nπ₀ ≥ 10 AND n(1−π₀) ≥ 10 for normality approximation
  2. Standard error uses π₀ (not p̂) in the test statistic
  3. Confidence interval uses p̂ in the standard error
  4. Effect size: Cohen's h = 2arcsin(√p̂) − 2arcsin(√π₀)
  5. Exact binomial test is more accurate for small n — prefer it when conditions aren't met
  6. Real applications: A/B testing, quality control, election polling

Advertisement

Need Expert Statistics Help?

Get personalized tutoring, dissertation support, or statistical consulting.

Advertisement