Why epiR::epi.conf Gives a Different Proportion Than Division

Summary

A discrepancy was identified between a manual calculation of cumulative incidence and the output of the epiR::epi.conf() function in R. While a simple frequentist division yielded 0.1215, the epiR package reported an estimate of 0.1383. This postmortem explores why “simple” math often fails in professional epidemiological software and how statistical methodologies differ from basic arithmetic.

Root Cause

The root cause is a mismatch between Point Estimation methods.

  • The manual calculation uses the Maximum Likelihood Estimate (MLE) for a binomial proportion, which is simply $p = x / n$.
  • The epiR::epi.conf() function, when called with method = "exact", utilizes the Clopper-Pearson interval logic or related exact binomial methods.
  • In many specialized epidemiological packages, the “estimate” returned is not always the raw proportion, but a value adjusted to be consistent with the exact confidence interval being calculated.
  • Specifically, when using “exact” methods, the software often accounts for the discrete nature of the binomial distribution, leading to an estimate that aligns with the interval bounds rather than a simple division.

Why This Happens in Real Systems

In production-grade statistical software, “correctness” is defined by mathematical rigor, not by how closely it matches a calculator.

  • Discrete Distribution Constraints: Binomial data is discrete. Traditional MLE assumes a continuous approximation that may not hold true for small sample sizes or specific edge cases.
  • Methodological Consistency: If a user requests an exact method, the package prioritizes the exact probability bounds. The reported “estimate” is often recalculated to ensure the interval is statistically consistent with the chosen distribution.
  • Parameterization: Different libraries use different parameterizations (e.g., estimating $p$ vs. estimating $\theta$ in a Beta distribution) which can shift the point estimate slightly.

Real-World Impact

  • Misinterpretation of Results: Stakeholders may believe the software is “broken” or “buggy” because it doesn’t match a spreadsheet.
  • Regulatory Friction: In clinical trials or public health reporting, a discrepancy between a manual report and an automated tool can trigger audit failures or delays in drug approval.
  • Decision Errors: If an engineer assumes the software is wrong and “corrects” it back to a simple MLE, they may inadvertently introduce under-coverage errors, where the confidence interval no longer captures the true parameter at the specified rate.

Example or Code (if necessary and relevant)

events <- 13
non_events <- 94
total <- events + non_events

# Manual MLE approach
risk_manual <- events / total
print(paste("Manual MLE:", risk_manual))

# epiR Exact approach
library(epiR)
mat <- matrix(c(events, non_events), nrow = 1, ncol = 2, byrow = TRUE)
res <- epi.conf(mat, ctype = "inc.risk", method = "exact")
print(res)

How Senior Engineers Fix It

Senior engineers approach these discrepancies through validation and documentation rather than blind debugging.

  • Verify the Underlying Algorithm: Instead of checking the result, check the documentation for the method. Confirm if method = "exact" implies a Clopper-Pearson, Wilson Score, or Agresti-Coull approach.
  • Unit Testing against Theory: Write tests that verify the output against mathematical properties (e.g., ensuring the interval coverage is correct) rather than testing against a hardcoded manual value.
  • Standardize Implementations: Ensure that all downstream services use the same statistical library version to prevent “drift” between different components of the pipeline.
  • Communicate Nuance: When reporting discrepancies to non-technical stakeholders, explain that the software is providing a statistically robust estimate rather than a naive estimate.

Why Juniors Miss It

  • The “Calculator Fallacy”: Juniors often assume that math is universal and that if $13/107 \neq 0.138$, the code must have a bug.
  • Lack of Statistical Depth: They often treat statistical functions as black-box arithmetic operators rather than implementations of complex probability theory.
  • Over-reliance on Intuition: They rely on “common sense” arithmetic instead of looking up the mathematical definition of the specific parameter (ctype = "inc.risk") within the package documentation.

Leave a Comment