The V Lab

Scope. This tutorial is an educational introduction, not a substitute for a protocol, statistical analysis plan, ethics review, or consultation with a biostatistician/epidemiologist. Examples are simplified so that the central ideas remain visible.

How to use this tutorial

Epidemiology studies the distribution and determinants of health-related states or events in specified populations, and applies that knowledge to improve population health. It connects clinical questions, public health action, causal reasoning, measurement, study design, and statistical analysis.

This document is designed for three kinds of use:

  1. First pass: read Sections 1–7 to build a conceptual map.
  2. Applied pass: run the R code and change the numbers in Sections 2, 3, 8, 11, and 12.
  3. Research pass: use Sections 9–16 as a checklist when developing a protocol or analysis plan.

All examples use base R, the stats package, or datasets distributed with R. No internet connection or external data file is required after the HTML is rendered.

Learning objectives

After working through the tutorial, you should be able to:

  • distinguish prevalence, cumulative incidence (risk), and incidence rate;
  • calculate and interpret risk ratios, odds ratios, rate ratios, and risk differences;
  • match a study design to a research question;
  • recognize selection bias, information bias, confounding, and effect modification;
  • evaluate a screening or diagnostic test;
  • outline an outbreak investigation;
  • express a causal question using a target population, exposure, comparator, outcome, and time horizon;
  • conduct a transparent analysis in R and report it without overstating causality;
  • identify common epidemiologic research areas and formulate answerable questions.

1. The epidemiologic way of thinking

1.1 Person, place, and time

Descriptive epidemiology begins by asking:

  • Person: Who is affected? Consider age, sex/gender, occupation, behaviors, comorbidities, social position, and other relevant characteristics.
  • Place: Where do events occur? Consider neighborhood, workplace, healthcare facility, region, and environmental context.
  • Time: When do events occur? Look for secular trends, seasonality, point-source clusters, latency, and changes following an intervention.

Description is not merely preliminary. It can identify inequities, reveal data quality problems, generate hypotheses, and guide urgent action.

1.2 Population, sample, and unit of analysis

The target population is the population to which the investigators want the answer to apply. The source population gives rise to the observed participants. The sample is the set actually measured. These may differ because of eligibility, access, consent, loss to follow-up, or incomplete records.

The unit may be a person, pregnancy, hospitalization, household, school, community, or person-time interval. Always state the unit. Treating repeated events from one person as if they were independent people can make uncertainty appear too small.

1.3 Exposure, outcome, covariate, and intervention

  • An exposure may be a behavior, treatment, infection, policy, environmental condition, or social determinant.
  • An outcome is the health state or event being studied.
  • A covariate is another measured variable used for description, precision, confounding control, prediction, or subgroup analysis.
  • An intervention is an action that could, at least conceptually, be assigned.

The same variable can play different roles in different questions. Blood pressure could be an exposure, an outcome, a mediator, or a confounder. Its role comes from the scientific question and causal structure, not from its column name.

1.4 Descriptive, predictive, and causal questions

These goals require different interpretations:

Goal Example Main concern
Descriptive What was diabetes prevalence in adults in 2025? Representative measurement
Predictive Who will be hospitalized in the next 30 days? Out-of-sample accuracy and calibration
Causal Would vaccination reduce hospitalization compared with no vaccination? A valid counterfactual comparison

An excellent prediction model does not automatically identify a causal effect, and a causal model need not predict each individual’s outcome well.

2. Measuring disease and health events

2.1 Counts, proportions, ratios, and rates

  • A count is a number of events (for example, 72 cases).
  • A proportion has a numerator included in its denominator and ranges from 0 to 1.
  • A ratio compares two quantities; the numerator need not be in the denominator.
  • A true rate includes time in the denominator and represents the speed at which events occur.

Every measure should specify its numerator, denominator, population, place, and time period. “The rate was 12%” is usually imprecise language: 12% is a proportion unless time is explicitly part of the denominator.

2.2 Prevalence

Point prevalence is the proportion of a population with a condition at a specified time:

Prevalence=existing cases at time tpopulation at time t. \text{Prevalence} = \frac{\text{existing cases at time }t}{\text{population at time }t}.

Period prevalence covers an interval rather than a single instant. Prevalence depends on both incidence and duration. It may rise because more new cases occur, survival improves, recovery slows, or case ascertainment improves.

2.3 Cumulative incidence (risk)

Risk is the proportion of initially outcome-free people who develop the outcome during a stated interval:

Risk=new cases during the intervalpeople at risk at the start. \text{Risk} = \frac{\text{new cases during the interval}} {\text{people at risk at the start}}.

Risk ranges from 0 to 1 and must include a time horizon: for example, “5-year risk.” The simple formula assumes sufficiently complete follow-up. With censoring and unequal follow-up, survival-analysis methods are generally needed.

2.4 Incidence rate (incidence density)

The incidence rate uses person-time at risk:

Incidence rate=new eventstotal person-time at risk. \text{Incidence rate} = \frac{\text{new events}} {\text{total person-time at risk}}.

Its units might be cases per 1,000 person-years. A person contributes time until the event, loss to follow-up, death, or study end, according to the protocol. Unlike risk, the rate is not a probability and can exceed 1 per chosen unit of time.

population <- 5000
existing_cases_day_1 <- 350
new_cases_one_year <- 90
initially_at_risk <- population - existing_cases_day_1
person_years <- 4380

point_prevalence <- existing_cases_day_1 / population
one_year_risk <- new_cases_one_year / initially_at_risk
incidence_rate <- new_cases_one_year / person_years

c(
  point_prevalence = point_prevalence,
  one_year_risk = one_year_risk,
  cases_per_1000_person_years = incidence_rate * 1000
)
##            point_prevalence               one_year_risk cases_per_1000_person_years
##                     0.07000                     0.01935                    20.54795

Interpretation:

  • 7.0% of the population had the condition at the starting date.
  • The one-year risk among people initially free of the condition was 1.9%.
  • Events occurred at 20.5 per 1,000 person-years.

2.5 Mortality, case fatality, and survival

  • Mortality risk/rate: deaths in the population denominator.
  • Cause-specific mortality: deaths attributed to a cause in the numerator; the population remains the denominator.
  • Case fatality proportion: deaths from a disease among people with that disease.
  • Survival proportion: proportion alive after a specified time among diagnosed people or a defined cohort.

Case fatality describes severity among cases; mortality also depends on how often the disease occurs in the population.

2.6 Crude, specific, and standardized measures

A crude measure combines the entire population. A stratum-specific measure is calculated within a category such as age group. Standardization creates a weighted summary that improves comparability when populations have different compositions.

In direct standardization, apply each study population’s stratum-specific rates to one common standard distribution.

standardization <- data.frame(
  age_group = c("0-39", "40-64", "65+"),
  standard_population = c(50000, 30000, 20000),
  rate_region_A = c(0.001, 0.006, 0.030),
  rate_region_B = c(0.0015, 0.005, 0.024)
)

standardization$expected_A <- with(
  standardization, standard_population * rate_region_A
)
standardization$expected_B <- with(
  standardization, standard_population * rate_region_B
)

age_standardized_A <- sum(standardization$expected_A) /
  sum(standardization$standard_population)
age_standardized_B <- sum(standardization$expected_B) /
  sum(standardization$standard_population)

standardization
c(region_A_per_1000 = 1000 * age_standardized_A,
  region_B_per_1000 = 1000 * age_standardized_B)
## region_A_per_1000 region_B_per_1000
##              8.30              7.05

Standardized rates are comparison summaries, not necessarily the observed rate in either population. Always report the standard population and method.

3. Measures of association and impact

3.1 The 2 x 2 table

For a binary exposure and outcome:

Outcome + Outcome - Total
Exposed a b a + b
Unexposed c d c + d

The exposed risk is a / (a + b) and unexposed risk is c / (c + d).

epi_2x2 <- function(tab) {
  stopifnot(all(dim(tab) == c(2, 2)), all(tab >= 0), all(rowSums(tab) > 0))
  a <- as.numeric(tab[1, 1]); b <- as.numeric(tab[1, 2])
  c <- as.numeric(tab[2, 1]); d <- as.numeric(tab[2, 2])

  p1 <- a / (a + b)
  p0 <- c / (c + d)
  safe_ratio <- function(num, den) {
    if (den == 0) {
      if (num == 0) NA_real_ else Inf
    } else {
      num / den
    }
  }
  rr <- safe_ratio(p1, p0)
  or <- safe_ratio(a * d, b * c)
  rd <- p1 - p0
  z <- qnorm(0.975)

  se_rd <- sqrt(p1 * (1 - p1) / (a + b) + p0 * (1 - p0) / (c + d))
  rr_ci <- or_ci <- c(NA_real_, NA_real_)
  if (a > 0 && c > 0 && is.finite(rr) && rr > 0) {
    se_log_rr <- sqrt(1 / a - 1 / (a + b) + 1 / c - 1 / (c + d))
    rr_ci <- exp(log(rr) + c(-1, 1) * z * se_log_rr)
  }
  if (all(c(a, b, c, d) > 0) && is.finite(or)) {
    se_log_or <- sqrt(1 / a + 1 / b + 1 / c + 1 / d)
    or_ci <- exp(log(or) + c(-1, 1) * z * se_log_or)
  }

  data.frame(
    measure = c("Risk exposed", "Risk unexposed", "Risk ratio",
                "Odds ratio", "Risk difference"),
    estimate = c(p1, p0, rr, or, rd),
    lower_95 = c(NA, NA,
                 rr_ci[1],
                 or_ci[1],
                 rd - z * se_rd),
    upper_95 = c(NA, NA,
                 rr_ci[2],
                 or_ci[2],
                 rd + z * se_rd),
    row.names = NULL
  )
}

tab <- matrix(c(80, 920,
                40, 960),
              nrow = 2, byrow = TRUE,
              dimnames = list(
                exposure = c("Exposed", "Unexposed"),
                outcome = c("Case", "Non-case")
              ))
tab
##            outcome
## exposure    Case Non-case
##   Exposed     80      920
##   Unexposed   40      960
epi_2x2(tab)

This teaching function reports a point estimate whenever it is mathematically defined. With zero cells, log-Wald intervals for RR or OR are returned as NA; exact, penalized, or other purpose-specific methods may be preferable in real small samples.

3.2 Relative measures

The risk ratio (RR) compares risks:

RR=risk in exposedrisk in unexposed. RR = \frac{\text{risk in exposed}}{\text{risk in unexposed}}.

  • RR = 1: equal risks.
  • RR > 1: greater risk in the exposed group.
  • RR < 1: lower risk in the exposed group.

The rate ratio compares incidence rates. The odds ratio (OR) compares odds:

OR=a/bc/d=adbc. OR = \frac{a/b}{c/d} = \frac{ad}{bc}.

The OR estimates the incidence rate ratio in incidence-density sampled case-control studies, and can approximate the risk ratio when the outcome is rare under suitable sampling. When the outcome is common, an OR can be much farther from 1 than the RR and should not be described as “times the risk.”

3.3 Absolute measures

The risk difference (RD) is:

RD=riskexposed−riskunexposed. RD = \text{risk}_{exposed} - \text{risk}_{unexposed}.

Absolute measures are crucial for decisions. A relative reduction of 50% could mean a drop from 40% to 20% (20 percentage points) or from 0.02% to 0.01% (0.01 percentage points).

At a stated follow-up horizon, when a causal interpretation is justified:

  • Number needed to treat (NNT) = 1 / absolute risk reduction.
  • Number needed to harm (NNH) = 1 / absolute risk increase.
  • Attributable fraction among exposed = (RR - 1) / RR for a harmful exposure.
  • Population attributable fraction combines association with exposure prevalence and requires strong causal assumptions.

NNT and NNH are conventionally rounded up to the next whole person, while the unrounded value may be retained for transparent calculation.

Using the example table, the risk difference is 4 percentage points, corresponding to an NNH of 25 if the association were truly causal and transportable.

3.4 Confidence intervals and p-values

A confidence interval describes the range generated by a procedure that would cover the true parameter at the stated frequency under repeated compatible sampling and model assumptions. It is not the probability that this particular interval contains the parameter.

A p-value measures compatibility between the observed data and a specified null model. It does not measure the probability that the null hypothesis is true, effect size, clinical importance, study quality, or absence of bias.

Report the estimate, confidence interval, units, model, and assumptions. Avoid turning continuous evidence into a binary conclusion at p = 0.05.

3.5 Association is scale-dependent

Effect modification can be present on one scale but not another. For example, a treatment may reduce risk by 10 percentage points in two subgroups (constant RD) while the subgroup RRs differ because their baseline risks differ. State the scale before claiming interaction.

4. Study designs

4.1 Overview

Design How participants are selected Typical measure Strength Main limitation
Case report/series By unusual outcome or clinical observation Counts/descriptions Early signal No comparison group
Ecologic Groups or populations Group-level correlation/rate ratio Policy/context questions Ecologic fallacy, limited individual control
Cross-sectional Sample at one time/period Prevalence, prevalence ratio Burden estimation Temporal order often unclear
Case-control By outcome status Odds ratio Efficient for rare outcomes/long latency Recall and selection mechanisms
Cohort By exposure/eligibility, then outcome follow-up Risk/rate ratio, risk difference Establishes exposure before incident outcome Time, cost, loss to follow-up
Randomized trial Random assignment to intervention Risk/rate differences and ratios Balances causes in expectation Ethics, adherence, generalizability
Quasi-experimental Exposure assigned by policy/time/threshold Design-specific contrast Evaluates natural/policy interventions Strong design assumptions

4.2 Cross-sectional studies

Cross-sectional studies are well suited to estimating burden and describing service needs. Because exposure and outcome are often measured together, it may be unclear whether the exposure preceded the outcome. Prevalence can also preferentially include long-duration survivors (prevalence-incidence bias).

4.3 Case-control studies

Investigators sample cases with the outcome and controls representing the exposure distribution in the population that produced those cases. Validity depends less on a fixed case-to-control ratio than on correct control selection.

Important variants include:

  • Nested case-control: cases and sampled controls arise within a defined cohort.
  • Case-cohort: controls are sampled from the cohort at baseline and may be reused.
  • Incidence-density sampling: controls are selected from people at risk when each case occurs; the OR estimates an incidence rate ratio.

Matching improves efficiency or controls design variables, but matched factors must be handled appropriately in analysis. Matching does not by itself eliminate confounding.

4.4 Cohort studies

Prospective cohorts follow participants forward from measurement. Retrospective cohorts reconstruct exposure and follow-up from existing records. Both require a clear time zero, eligibility rule, exposure strategy, follow-up definition, and outcome ascertainment.

A common error is immortal time bias: a period during which a participant must remain event-free to become classified as exposed is incorrectly counted as exposed time. Align eligibility, treatment assignment, and start of follow-up.

4.5 Randomized trials

Randomization supports exchangeability in expectation, allocation concealment protects the assignment process, and blinding may reduce differential behavior or measurement.

  • Intention-to-treat estimates the effect of assignment under real adherence.
  • Per-protocol targets adherence to the protocol but usually needs adjustment for post-randomization selection/confounding.

Report harms as well as benefits, participant flow, missing outcomes, protocol changes, and prespecified versus exploratory analyses.

4.6 Quasi-experimental designs

Interrupted time series, difference-in-differences, regression discontinuity, and instrumental-variable designs can answer questions when randomization is unavailable. Each substitutes a specific assumption for random assignment—for example, parallel trends for difference-in-differences or continuity around a threshold for regression discontinuity. These assumptions should be explained and probed, not hidden behind a model name.

4.7 Choosing a design

Ask in order:

  1. What is the exact estimand or descriptive target?
  2. Can exposure/intervention and outcome be ethically randomized?
  3. Is the outcome rare, delayed, recurrent, or quickly observed?
  4. Can the source population and time zero be identified?
  5. How accurate are exposure, outcome, and confounder measurements?
  6. What selection and missing-data mechanisms are likely?
  7. What design is feasible with the available time, budget, and sample size?

5. Bias, random error, and measurement

5.1 Random error versus systematic error

Random error creates imprecision and generally decreases with more information. Systematic error (bias) shifts estimates because of study design, conduct, measurement, or analysis. A very large biased study can produce a very precise wrong answer.

5.2 Selection bias

Selection bias occurs when inclusion, participation, retention, or analysis depends on variables in a way that distorts the target comparison. Examples include:

  • nonresponse related to both exposure and outcome;
  • loss to follow-up related to prognosis and exposure;
  • restricting analysis to people who survived long enough to enter a registry;
  • conditioning on hospitalization when exposure and disease both cause admission;
  • the healthy-worker survivor effect.

Prevention starts with source-population definition, inclusive recruitment, and active follow-up. Analysis may use standardization, inverse-probability weighting, or sensitivity analysis, but only with defensible measured predictors of selection.

5.3 Information bias and misclassification

Information bias arises from inaccurate measurement. Examples include recall bias, interviewer bias, diagnostic suspicion, imperfect coding, and instrument drift.

  • Nondifferential misclassification: measurement properties do not differ across the compared groups, conditional on the true value.
  • Differential misclassification: sensitivity or specificity differs by outcome, exposure, or another comparison-defining variable.

Nondifferential misclassification of a binary exposure often—but not always—biases a ratio toward the null. The direction is not guaranteed for multicategory variables, dependent errors, or complex analyses.

Improve measurement with validated definitions, standardized training, calibration, blinded outcome assessment where feasible, repeated measurements, and adjudication.

5.4 Confounding

Confounding mixes the exposure effect with differences in causes of the outcome between exposure groups. A classical confounder:

  1. causes or predicts the outcome;
  2. is associated with exposure in the source population; and
  3. is not a consequence of the exposure.

These rules are helpful but causal knowledge is more reliable than significance tests or automatic change-in-estimate procedures. Do not adjust for every available variable: mediators, colliders, and poorly measured proxies can increase bias.

Design approaches include randomization, restriction, and matching. Analysis approaches include stratification, standardization, regression adjustment, matching/weighting by a propensity score, and inverse-probability weighting.

5.5 Stratification and the Mantel-Haenszel odds ratio

Suppose age is a potential confounder. Compare exposure and outcome within age strata before producing a summary.

# Each 2 x 2 table uses rows = exposed/unexposed and columns = case/non-case.
young <- matrix(c(10, 90,
                  25, 475), nrow = 2, byrow = TRUE)
older <- matrix(c(250, 250,
                  33, 67), nrow = 2, byrow = TRUE)
strata <- list(younger = young, older = older)

stratum_or <- vapply(strata, function(x) {
  (x[1, 1] * x[2, 2]) / (x[1, 2] * x[2, 1])
}, numeric(1))

mh_num <- sum(vapply(strata, function(x) {
  x[1, 1] * x[2, 2] / sum(x)
}, numeric(1)))
mh_den <- sum(vapply(strata, function(x) {
  x[1, 2] * x[2, 1] / sum(x)
}, numeric(1)))

crude <- Reduce(`+`, strata)
crude_or <- (crude[1, 1] * crude[2, 2]) / (crude[1, 2] * crude[2, 1])
c(crude_or = crude_or, stratum_or,
  mantel_haenszel_or = mh_num / mh_den)
##           crude_or            younger              older mantel_haenszel_or
##              7.146              2.111              2.030              2.048

The stratum-specific ORs are both close to 2, and the Mantel-Haenszel summary is also about 2, whereas the crude OR is much larger because exposed participants are disproportionately older. This is a deliberately strong confounding example. A pooled summary is meaningful only when stratum-specific effects are sufficiently compatible for the scientific purpose; otherwise, report the variation rather than hiding it.

5.6 Effect modification (interaction)

Effect modification means the effect differs across levels of another variable. It is not a nuisance to “control away”; it can be the central finding. Prespecify scientifically important modifiers, report subgroup-specific estimates and uncertainty, and avoid claiming subgroup differences merely because one subgroup has p < 0.05 and another does not. Test or estimate the difference between effects.

5.7 Other recurring biases

  • Length bias: screening more often finds slowly progressing disease.
  • Lead-time bias: earlier diagnosis appears to prolong survival without delaying death.
  • Detection/surveillance bias: one group is examined more intensely.
  • Time-window bias: exposure opportunity differs between compared groups.
  • Overadjustment: conditioning on mediators or their descendants.
  • Collider bias: conditioning on a common effect opens a noncausal path.
  • Regression to the mean: extreme measurements tend to be less extreme when repeated, even without treatment.

6. Causal thinking

6.1 Potential outcomes and causal contrasts

For one person, imagine the outcome under exposure and the outcome under no exposure. Their difference is an individual causal effect, but only one can be observed. Studies therefore compare groups and need a design/analysis that makes the observed comparison stand in for the missing counterfactual.

Common identifying conditions include:

  • Consistency: the observed outcome under the received exposure corresponds to the defined potential outcome; exposure versions are sufficiently specified.
  • Exchangeability: compared groups would have had comparable potential outcomes, conditional on the adjustment set.
  • Positivity: every relevant covariate pattern has a nonzero probability of each exposure strategy being compared.
  • Correct time order: causes precede outcomes, with time zero aligned across groups.
  • No important interference, or a clearly defined framework when one person’s exposure affects another person’s outcome.

These are scientific assumptions, not properties that software can verify completely.

6.2 Directed acyclic graphs (DAGs)

A DAG encodes assumed causal relationships:

Confounder C  ---> Exposure E
Confounder C  ---> Outcome Y
Exposure E    ---> Outcome Y
Exposure E    ---> Mediator M ---> Outcome Y

The edge list states unambiguously that C is a common cause and that M lies on one causal pathway from E to Y. Use arrows to state assumptions before choosing covariates. Adjust for common causes of exposure and outcome to block backdoor paths. Do not routinely adjust for mediators or colliders. A DAG cannot tell you whether an omitted arrow is truly absent; its value is making assumptions explicit and debatable.

6.3 The target-trial framework

Even for observational data, specify the hypothetical trial:

Component Question to specify
Eligibility Who would enter, and when?
Strategies What exactly are the exposure/intervention alternatives?
Assignment How is assignment emulated, and which baseline confounders must be controlled?
Time zero When do eligibility, assignment, and follow-up begin?
Outcome What definition and ascertainment window are used?
Causal contrast Intention-to-treat-like or per-protocol-like?
Analysis How are censoring, competing events, and confounding handled?

This prevents common errors such as using future information to define baseline exposure or giving one group guaranteed event-free time.

6.4 Mediation and competing events

Mediation asks how much of an effect operates through a specified pathway. Direct and indirect effects require assumptions beyond total-effect estimation, including control of mediator-outcome confounding and careful definition when exposure affects that confounding.

A competing event prevents the outcome of interest (for example, death before dementia diagnosis). Whether to estimate a cause-specific hazard, cumulative incidence, or a hypothetical risk if the competing event were eliminated depends on the research question. Treating all competing events as ordinary independent censoring is often misleading.

7. Screening and diagnostic accuracy

7.1 Core measures

Against a reference standard:

Disease + Disease -
Test + True positive (TP) False positive (FP)
Test - False negative (FN) True negative (TN)
  • Sensitivity = TP / (TP + FN)
  • Specificity = TN / (FP + TN)
  • Positive predictive value (PPV) = TP / (TP + FP)
  • Negative predictive value (NPV) = TN / (FN + TN)
  • Positive likelihood ratio (LR+) = sensitivity / (1 - specificity)
  • Negative likelihood ratio (LR-) = (1 - sensitivity) / specificity
diagnostic_metrics <- function(tp, fp, fn, tn) {
  sensitivity <- tp / (tp + fn)
  specificity <- tn / (fp + tn)
  ppv <- tp / (tp + fp)
  npv <- tn / (fn + tn)
  accuracy <- (tp + tn) / (tp + fp + fn + tn)
  c(
    sensitivity = sensitivity,
    specificity = specificity,
    PPV = ppv,
    NPV = npv,
    LR_positive = sensitivity / (1 - specificity),
    LR_negative = (1 - sensitivity) / specificity,
    accuracy = accuracy
  )
}

diagnostic_metrics(tp = 85, fp = 90, fn = 15, tn = 810)
## sensitivity specificity         PPV         NPV LR_positive LR_negative    accuracy
##      0.8500      0.9000      0.4857      0.9818      8.5000      0.1667      0.8950

7.2 Predictive values depend on prevalence

For fixed sensitivity and specificity, PPV increases as pretest probability/prevalence increases, while NPV generally decreases.

sens <- 0.90
spec <- 0.95
prevalence <- seq(0.001, 0.50, length.out = 300)

ppv <- sens * prevalence /
  (sens * prevalence + (1 - spec) * (1 - prevalence))
npv <- spec * (1 - prevalence) /
  ((1 - sens) * prevalence + spec * (1 - prevalence))

plot(prevalence, ppv, type = "l", lwd = 2, col = "#b2182b",
     ylim = c(0, 1), xlab = "Prevalence / pretest probability",
     ylab = "Predictive value")
lines(prevalence, npv, lwd = 2, col = "#2166ac")
legend("right", c("PPV", "NPV"), lwd = 2,
       col = c("#b2182b", "#2166ac"), bty = "n")

This is why a test that performs well in a specialty clinic can yield many false positives in low-risk population screening.

7.3 Thresholds, ROC curves, and utility

Lowering a continuous test threshold usually increases sensitivity and decreases specificity. A receiver operating characteristic (ROC) curve shows sensitivity versus 1-specificity across thresholds. The area under the curve measures discrimination, not calibration or clinical usefulness.

Choose thresholds using consequences: missed disease, false positives, treatment harms, costs, capacity, equity, and patient preferences. A screening program should also have an important detectable condition, an acceptable test, effective early management, a pathway for follow-up, and evidence that benefits exceed harms.

7.4 Spectrum and verification bias

Accuracy can vary with disease severity, comorbidity, age, and setting (spectrum effects). If only test-positive people receive the reference standard, verification bias can inflate apparent accuracy. Evaluate tests in the intended-use population and report indeterminate results rather than silently excluding them.

8. Outbreak investigation

Outbreak investigation combines rapid action with disciplined inference. Steps may overlap:

  1. Prepare field, laboratory, data, ethics, and communication resources.
  2. Establish that observed cases exceed the expected level.
  3. Verify diagnosis and laboratory findings.
  4. Construct a case definition (clinical, person, place, time, and certainty level).
  5. Find cases actively and create a line list.
  6. Describe cases by time, place, and person.
  7. Generate hypotheses using interviews, environmental inspection, and known biology.
  8. Evaluate hypotheses with analytic and laboratory/environmental evidence.
  9. Refine hypotheses and conduct additional studies when needed.
  10. Implement control measures as soon as warranted; do not always wait for the final analysis.
  11. Communicate findings, uncertainty, recommendations, and follow-up plans.

8.1 Epidemic curves

  • A narrow peak within one incubation period suggests a point source.
  • A plateau or extended exposure window can suggest a continuous common source.
  • Successive waves separated by an incubation period can suggest propagated spread.

Reporting delays and active case finding also shape the curve, so pattern recognition must be combined with contextual evidence.

8.2 Attack rates and a food-specific example

An attack rate is a cumulative incidence proportion over an outbreak period.

# 80 of 200 people who ate a food became ill; 20 of 200 non-eaters became ill.
food_table <- matrix(c(80, 120,
                       20, 180),
                     nrow = 2, byrow = TRUE,
                     dimnames = list(
                       food = c("Ate food", "Did not eat"),
                       outcome = c("Ill", "Not ill")
                     ))
food_table
##              outcome
## food          Ill Not ill
##   Ate food     80     120
##   Did not eat  20     180
epi_2x2(food_table)

The exposed attack rate is 40%, the unexposed attack rate is 10%, the RR is 4, and the risk difference is 30 percentage points. Food histories, incubation periods, dose, other menu items, food handling, laboratory findings, and selection into the event still matter for causal interpretation.

8.3 Reproduction number and epidemic growth

The basic reproduction number, R0, is the expected number of secondary infections from a typical infectious person in a wholly susceptible population under specified conditions. The effective reproduction number, Rt, changes with immunity, behavior, interventions, contact patterns, and pathogen characteristics. It is inferred from data using a generation/serial interval distribution and is not an immutable pathogen constant.

9. From an idea to an answerable research question

9.1 PECO/PICO

Structure an etiologic question with Population, Exposure (or Intervention), Comparator, Outcome, and a time horizon.

Weak question:

Does air pollution affect health?

More answerable question:

Among adults aged 65 years or older living in Calgary during 2022–2026, what is the 7-day change in cardiovascular hospitalization risk associated with a 10 microgram/m3 increase in daily PM2.5, compared with lower exposure days?

The refined question identifies population, contrast, outcome, exposure window, and outcome window. It still needs a causal estimand, exposure model, confounder plan, seasonality control, and strategy for repeated daily observations.

9.2 Common estimands

An estimand precisely describes what is being estimated. Examples include:

  • prevalence in a target population at a date;
  • 5-year risk under treatment versus no treatment;
  • average risk difference if everyone followed strategy A versus strategy B;
  • incidence rate ratio per 10-unit exposure increase;
  • vaccine effectiveness, often expressed as 1 - RR under a justified design;
  • change in an outcome level or slope after a policy;
  • sensitivity and specificity at a prespecified threshold.

Specify population, treatment/exposure strategies, outcome, time horizon, summary measure, and handling of intercurrent events.

9.3 Protocol essentials

A protocol should prespecify:

  • rationale, objectives, and hypotheses;
  • target/source populations and recruitment;
  • eligibility, time zero, and follow-up;
  • operational exposure, comparator, and outcome definitions;
  • causal diagram and confounder set when the goal is causal;
  • sample-size rationale;
  • primary/secondary analyses and effect scales;
  • missing data, measurement error, censoring, and competing events;
  • subgroup and sensitivity analyses;
  • data management, privacy, ethics, and dissemination;
  • version control and a record of deviations.

10. Common epidemiologic research areas and questions

10.1 Infectious disease epidemiology

Common questions concern transmission, reservoirs, incubation, vaccine effectiveness, variant dynamics, antimicrobial resistance, contact networks, and control strategies.

Examples:

  • What household characteristics modify secondary attack risk?
  • How effective is a booster against severe disease over six months?
  • Did a school ventilation policy change absence-associated respiratory illness?

Important issues include dependent transmission, time-varying immunity, test-seeking, under-ascertainment, and rapidly changing interventions.

10.2 Chronic disease epidemiology

Research spans cardiovascular disease, cancer, diabetes, respiratory disease, mental health, and multimorbidity. Long latency, changing exposure, survival, competing risks, and repeated measures are common.

Examples:

  • How is long-term blood pressure pattern associated with stroke incidence?
  • What fraction of diabetes burden is associated with modifiable risk factors?
  • Are screening benefits and harms different across baseline-risk groups?

10.3 Environmental and occupational epidemiology

Topics include air pollution, heat, water contamination, noise, chemicals, radiation, physical workload, shift work, and workplace injury. Exposure assignment, mixtures, spatial correlation, time trends, healthy-worker bias, and policy confounding are key.

Examples:

  • Does wildfire smoke increase acute respiratory visits in the following week?
  • What is the hearing-loss rate across cumulative occupational noise categories?
  • Did a heat-warning system reduce heat-related mortality?

10.4 Social epidemiology and health equity

Social epidemiology examines how power, policy, material conditions, discrimination, housing, education, income, and social networks shape health. Categories such as race and ethnicity should be conceptualized in relation to racism and social processes, not treated as innate biological causes without justification.

Equity analyses should ask who benefits, who is harmed, whose data are missing, whether measurement works similarly across groups, and whether interventions change absolute as well as relative disparities.

10.5 Pharmacoepidemiology and comparative effectiveness

Common questions address real-world benefits and harms of medications and devices. Recurring challenges include confounding by indication, contraindication, new-user versus prevalent-user design, adherence, treatment switching, depletion of susceptible people, and immortal time.

An active-comparator new-user design often improves comparability by contrasting people initiating therapies used for the same indication and aligning time zero at initiation.

10.6 Maternal, child, aging, and life-course epidemiology

These fields deal with changing susceptibility, developmental windows, familial clustering, fertility selection, pregnancy as a time-varying process, and survival into older ages. Specify whether inference concerns pregnancies, births, parents, children, or families, and handle repeated pregnancies or siblings appropriately.

10.7 Injury and violence epidemiology

Research may examine road design, protective equipment, substance use, firearm policy, falls, or workplace systems. Exposure opportunity is central: counts of crashes, for example, should be interpreted relative to travel distance, trips, time, or another appropriate denominator.

10.8 Genetic and molecular epidemiology

Topics include heritability, genome-wide association, gene-environment interplay, biomarkers, and Mendelian randomization. Population structure, selection, multiple testing, weak instruments, pleiotropy, tissue specificity, and measurement timing need careful attention. Genetic association does not imply deterministic individual fate.

10.9 Surveillance and implementation research

Surveillance continuously and systematically collects, analyzes, interprets, and shares data for action. Evaluate timeliness, sensitivity, representativeness, stability, simplicity, acceptability, data quality, and positive predictive value.

Implementation research asks not only whether an intervention can work, but how reach, adoption, fidelity, adaptation, cost, and context influence real-world impact.

10.10 Example research-question matrix

Area Descriptive question Analytic/causal question Possible design
Infection What is weekly incidence? Did vaccination reduce severe disease? Surveillance + target-trial emulation
Cancer What is stage distribution at diagnosis? Does screening reduce disease-specific mortality? Trial or carefully designed cohort
Environment Where are heat-related visits concentrated? Did cooling centers reduce heat illness? Spatial description + quasi-experiment
Medication safety What adverse events are reported? Does drug A increase bleeding versus drug B? Active-comparator new-user cohort
Equity How does coverage vary by neighborhood? Did universal coverage narrow absolute disparities? Repeated cross-sections / policy evaluation
Occupation What is injury incidence by job? Does a safety program reduce injury rates? Cluster trial or interrupted time series

11. A reproducible analysis workflow in R

11.1 Preserve raw data and metadata

Keep raw data read-only. Record provenance, extraction date, inclusion rules, variable definitions, units, value labels, missing-value codes, and transformations. A minimal data dictionary includes variable name, meaning, type, allowed values, timing, source, and known limitations.

Never display real identifiers or row-level sensitive data in a report. The simulated data below are safe because they do not represent real people.

11.2 Simulate a fixed five-year cohort for teaching

The simulated participants are disease-free at baseline and all complete five years of follow-up. The binary outcome disease_5y therefore represents incident disease by five years, giving every risk below an explicit and common time horizon.

n <- 2500
cohort <- data.frame(
  id = seq_len(n),
  age = round(pmin(pmax(rnorm(n, mean = 52, sd = 14), 18), 85)),
  sex = factor(sample(c("Female", "Male"), n, replace = TRUE)),
  activity = round(pmax(rnorm(n, mean = 150, sd = 70), 0))
)

# Smoking probability varies with age and sex, creating measured confounding.
logit_smoke <- -0.5 + 0.012 * (cohort$age - 50) +
  0.25 * (cohort$sex == "Male")
cohort$smoker <- rbinom(n, 1, plogis(logit_smoke))

# Five-year incident disease depends on smoking, age, sex, and activity.
logit_disease_5y <- -3.6 + 0.75 * cohort$smoker +
  0.045 * (cohort$age - 50) +
  0.20 * (cohort$sex == "Male") -
  0.002 * (cohort$activity - 150)
cohort$disease_5y <- rbinom(n, 1, plogis(logit_disease_5y))

head(cohort)

11.3 Data-quality checks

Checks should be driven by meaning, not only by software type.

quality_summary <- data.frame(
  variable = names(cohort),
  class = vapply(cohort, function(x) class(x)[1], character(1)),
  missing_n = vapply(cohort, function(x) sum(is.na(x)), integer(1)),
  unique_n = vapply(cohort, function(x) length(unique(x)), integer(1)),
  row.names = NULL
)
quality_summary
stopifnot(
  !anyDuplicated(cohort$id),
  all(cohort$age >= 18 & cohort$age <= 85),
  all(cohort$smoker %in% c(0, 1)),
  all(cohort$disease_5y %in% c(0, 1))
)

Also examine impossible date sequences, duplicate events, unit changes, denominator coverage, category drift over time, and whether missingness is encoded as values such as 9, 99, blank, or “unknown.”

11.4 Describe before modeling

overall_summary <- data.frame(
  n = nrow(cohort),
  mean_age = mean(cohort$age),
  sd_age = sd(cohort$age),
  median_activity = median(cohort$activity),
  smoking_prevalence = mean(cohort$smoker),
  five_year_disease_risk = mean(cohort$disease_5y)
)
overall_summary
with(cohort, table(smoker, disease_5y))
##       disease_5y
## smoker    0    1
##      0 1399   47
##      1  960   94
with(cohort, prop.table(table(smoker, disease_5y), margin = 1))
##       disease_5y
## smoker       0       1
##      0 0.96750 0.03250
##      1 0.91082 0.08918
boxplot(activity ~ smoker, data = cohort,
        names = c("Non-smoker", "Smoker"),
        ylab = "Activity (minutes/week)",
        col = c("#9ecae1", "#fdae6b"))

Description reveals coding errors, sparse groups, lack of overlap, nonlinear patterns, and whether the planned estimand is supported by the data.

11.5 Crude 2 x 2 analysis

cohort_tab <- with(cohort, table(
  factor(smoker, levels = c(1, 0), labels = c("Smoker", "Non-smoker")),
  factor(disease_5y, levels = c(1, 0), labels = c("Case", "Non-case"))
))
cohort_tab
##
##              Case Non-case
##   Smoker       94      960
##   Non-smoker   47     1399
epi_2x2(cohort_tab)

This comparison is unadjusted. Because age and sex affect smoking probability and five-year disease risk in the simulation, the crude association does not isolate a smoking effect.

11.6 Logistic regression

Logistic regression models log odds. Exponentiated coefficients are adjusted odds ratios, conditional on included variables and model form.

fit_crude <- glm(disease_5y ~ smoker, family = binomial(), data = cohort)
fit_adjusted <- glm(
  disease_5y ~ smoker + age + sex + activity,
  family = binomial(), data = cohort
)

coefficient_table <- function(model) {
  sm <- summary(model)$coefficients
  data.frame(
    term = rownames(sm),
    odds_ratio = exp(sm[, "Estimate"]),
    lower_95 = exp(sm[, "Estimate"] - 1.96 * sm[, "Std. Error"]),
    upper_95 = exp(sm[, "Estimate"] + 1.96 * sm[, "Std. Error"]),
    p_value = sm[, "Pr(>|z|)"],
    row.names = NULL,
    check.names = FALSE
  )
}

coefficient_table(fit_crude)
coefficient_table(fit_adjusted)

Check functional form: the linearly entered age coefficient assumes a constant change in log odds per year. Splines are often preferable to arbitrary categorization, but require additional tools beyond this package-free tutorial.

11.7 Standardized risks from a regression model

Odds ratios are not risks. Regression standardization can translate a fitted model to marginal five-year risks under two exposure scenarios.

data_smoke <- transform(cohort, smoker = 1)
data_no_smoke <- transform(cohort, smoker = 0)

risk_if_all_smoked <- mean(predict(
  fit_adjusted, newdata = data_smoke, type = "response"
))
risk_if_none_smoked <- mean(predict(
  fit_adjusted, newdata = data_no_smoke, type = "response"
))

standardized_effects <- c(
  risk_if_all_smoked = risk_if_all_smoked,
  risk_if_none_smoked = risk_if_none_smoked,
  standardized_risk_difference = risk_if_all_smoked - risk_if_none_smoked,
  standardized_risk_ratio = risk_if_all_smoked / risk_if_none_smoked
)
standardized_effects
##           risk_if_all_smoked          risk_if_none_smoked standardized_risk_difference
##                      0.08600                      0.03346                      0.05254
##      standardized_risk_ratio
##                      2.57041

These g-computation estimates have a causal interpretation only if exchangeability, positivity, consistency, measurement, model, and selection assumptions are adequate. The simple calculation also omits uncertainty intervals.

11.8 Interaction example

fit_interaction <- glm(
  disease_5y ~ smoker * sex + age + activity,
  family = binomial(), data = cohort
)
coefficient_table(fit_interaction)
# Standardized smoking risks within sex to assess additive and relative scales.
standardize_within_sex <- function(sex_value) {
  subgroup <- cohort[cohort$sex == sex_value, ]
  p1 <- mean(predict(fit_interaction,
                     newdata = transform(subgroup, smoker = 1),
                     type = "response"))
  p0 <- mean(predict(fit_interaction,
                     newdata = transform(subgroup, smoker = 0),
                     type = "response"))
  c(risk_exposed = p1, risk_unexposed = p0,
    risk_difference = p1 - p0, risk_ratio = p1 / p0)
}

rbind(
  Female = standardize_within_sex("Female"),
  Male = standardize_within_sex("Male")
)
##        risk_exposed risk_unexposed risk_difference risk_ratio
## Female      0.07410        0.03016         0.04394      2.457
## Male        0.09763        0.03664         0.06099      2.664

The simulation did not include a smoking-by-sex interaction on the log-odds scale. Subgroup RDs and RRs can nevertheless differ systematically because baseline risks differ and interaction is scale-specific; sampling variation adds further differences. Report the effect scale, uncertainty intervals, and scientific context.

11.9 Count and rate models

Poisson regression can model event counts with log person-time as an offset.

n_units <- 800
rate_data <- data.frame(
  exposed = rbinom(n_units, 1, 0.35),
  age10 = rnorm(n_units, 0, 1),
  person_years = runif(n_units, 0.5, 4)
)
true_rate <- exp(-3.2 + 0.55 * rate_data$exposed + 0.25 * rate_data$age10)
rate_data$events <- rpois(n_units, true_rate * rate_data$person_years)

rate_fit <- glm(
  events ~ exposed + age10 + offset(log(person_years)),
  family = poisson(), data = rate_data
)
rate_sm <- summary(rate_fit)$coefficients
data.frame(
  term = rownames(rate_sm),
  rate_ratio = exp(rate_sm[, "Estimate"]),
  lower_95 = exp(rate_sm[, "Estimate"] - 1.96 * rate_sm[, "Std. Error"]),
  upper_95 = exp(rate_sm[, "Estimate"] + 1.96 * rate_sm[, "Std. Error"]),
  row.names = NULL
)
dispersion_statistic <- sum(residuals(rate_fit, type = "pearson")^2) /
  df.residual(rate_fit)
dispersion_statistic
## [1] 1.008

The offset fixes the coefficient of log person-time at 1, converting expected counts to rates. Strong overdispersion, clustering, excess zeros, or recurrent-event dependence requires a more appropriate variance/model strategy.

11.10 Grouped case-control example using esoph

The built-in esoph dataset contains grouped cases and controls in a study of esophageal cancer, age, alcohol consumption, and tobacco consumption. Its grouping variables are ordered factors, so they are explicitly converted to unordered factors below; R’s default treatment contrasts then compare each category with the first.

data(esoph, package = "datasets")
head(esoph)
esoph_model <- transform(
  esoph,
  agegp = factor(agegp, levels = levels(agegp), ordered = FALSE),
  alcgp = factor(alcgp, levels = levels(alcgp), ordered = FALSE),
  tobgp = factor(tobgp, levels = levels(tobgp), ordered = FALSE)
)

esoph_fit <- glm(
  cbind(ncases, ncontrols) ~ agegp + alcgp + tobgp,
  family = binomial(), data = esoph_model
)

esoph_sm <- summary(esoph_fit)$coefficients
esoph_results <- data.frame(
  term = rownames(esoph_sm),
  odds_ratio = exp(esoph_sm[, "Estimate"]),
  lower_95 = exp(esoph_sm[, "Estimate"] - 1.96 * esoph_sm[, "Std. Error"]),
  upper_95 = exp(esoph_sm[, "Estimate"] + 1.96 * esoph_sm[, "Std. Error"]),
  row.names = NULL
)
esoph_results

The first level of each factor is the reference category. Interpretation still depends on the original sampling and measurement process; model output alone is not a study design.

11.11 Built-in aggregate data: Titanic

The Titanic table illustrates stratified risks, although it is not a modern health study and its categories reflect historical records.

data(Titanic, package = "datasets")
titanic <- as.data.frame(Titanic)

sex_survival <- xtabs(Freq ~ Sex + Survived, data = titanic)
sex_survival
##         Survived
## Sex        No  Yes
##   Male   1364  367
##   Female  126  344
cbind(
  total = rowSums(sex_survival),
  survival_risk = sex_survival[, "Yes"] / rowSums(sex_survival)
)
##        total survival_risk
## Male    1731        0.2120
## Female   470        0.7319
class_survival <- xtabs(Freq ~ Class + Survived, data = titanic)
cbind(
  total = rowSums(class_survival),
  survival_risk = class_survival[, "Yes"] / rowSums(class_survival)
)
##      total survival_risk
## 1st    325        0.6246
## 2nd    285        0.4140
## 3rd    706        0.2521
## Crew   885        0.2395

These are crude associations. Differences by passenger class, sex, age, evacuation process, and record completeness are intertwined; the table should not be turned into an individual causal claim.

11.12 Ecologic caution using state.x77

state_data <- as.data.frame(state.x77)
correlation <- cor(state_data$Illiteracy, state_data$`Life Exp`)
correlation
## [1] -0.5885
plot(state_data$Illiteracy, state_data$`Life Exp`,
     pch = 19, col = "#2c7fb8",
     xlab = "State-level illiteracy (%)",
     ylab = "State-level life expectancy (years)")
abline(lm(`Life Exp` ~ Illiteracy, data = state_data),
       col = "#d95f0e", lwd = 2)

A state-level association does not establish that individuals with one characteristic experience the corresponding individual outcome. Group composition, historical context, policy, and many shared causes can produce the pattern.

12. Missing data, censoring, and sensitivity analysis

12.1 Missing-data mechanisms as working assumptions

  • MCAR: missingness is unrelated to observed or unobserved values (rarely plausible in full).
  • MAR: conditional on observed variables in the model, missingness does not depend on the missing value.
  • MNAR: missingness still depends on unobserved values after conditioning.

These labels describe assumptions relative to an analysis and observed-variable set. They cannot usually be proven from the incomplete data.

Complete-case analysis may lose precision and be biased. Single mean imputation understates uncertainty and distorts relationships. Multiple imputation can be useful when its model, auxiliary variables, time ordering, and estimand are appropriate, but it does not repair systematically unmeasured information.

12.2 Demonstrating missingness

cohort_missing <- cohort
missing_probability <- plogis(-3 + 0.025 * (cohort_missing$age - 50) +
                              0.8 * cohort_missing$disease_5y)
cohort_missing$activity[rbinom(n, 1, missing_probability) == 1] <- NA

c(
  missing_activity = mean(is.na(cohort_missing$activity)),
  missing_among_cases = with(cohort_missing,
    mean(is.na(activity[disease_5y == 1]))),
  missing_among_non_cases = with(cohort_missing,
    mean(is.na(activity[disease_5y == 0])))
)
##        missing_activity     missing_among_cases missing_among_non_cases
##                 0.06080                 0.17021                 0.05426

Because missingness here depends on outcome and age, simply describing an overall missing percentage hides a meaningful pattern.

12.3 Censoring and loss to follow-up

Censoring is not synonymous with missing a covariate. In time-to-event analyses it means the event time is only partially observed. Standard survival methods rely on independent/noninformative censoring conditional on modeled variables. If prognosis affects dropout differently across exposure groups, inverse-probability-of-censoring weights or sensitivity analyses may be needed.

12.4 Sensitivity analyses

Useful sensitivity analyses target the most consequential assumptions:

  • alternative valid outcome/exposure definitions;
  • plausible lag and induction periods;
  • alternate confounder sets justified by different causal assumptions;
  • quantitative bias analysis for unmeasured confounding or misclassification;
  • bounds for missing outcomes;
  • negative-control exposures or outcomes;
  • positive-control outcomes;
  • alternate approaches to censoring or competing events;
  • model functional forms and influential observations.

Do not search across analyses until one becomes “significant.” Prespecify primary choices and explain why each sensitivity analysis probes a specific vulnerability.

13. Sample size, power, and precision

Sample-size planning should follow the primary estimand and design. Inputs may include baseline risk/rate, smallest important effect, exposure prevalence or allocation ratio, follow-up, clustering, repeated measures, design effect, expected missingness, and planned adjustment.

Power is a long-run probability under a specified true effect and analysis plan. It is not the probability that the study hypothesis is true. After data collection, an observed confidence interval is more informative than “post hoc power,” which largely restates the p-value.

Rare outcomes can leave few effective events even in a large database. The number of rows is not the same as information: clustering, imbalance, poor overlap, and measurement error reduce effective information.

14. Ethics, equity, privacy, and community partnership

Epidemiologic quality includes ethical quality.

  • Obtain appropriate research ethics or public-health authority review.
  • Minimize data collection and access; use secure environments and disclosure review.
  • Explain consent or justified waivers, linkage, secondary use, and retention.
  • Engage communities affected by the question, especially for stigmatized outcomes or historically extractive research.
  • Anticipate harms from labels, maps, small cells, predictive scores, and algorithmic deployment.
  • Assess performance and impact across relevant groups without treating social categories as biologic essences.
  • Return useful findings in accessible formats and acknowledge uncertainty.

Small-cell suppression alone may not prevent re-identification when tables can be combined. Follow applicable law, institutional policy, and data-governance agreements.

15. Reporting and interpretation

15.1 A transparent results paragraph

A strong paragraph usually gives:

  1. the population and design;
  2. group denominators and event counts;
  3. absolute risks/rates;
  4. relative and absolute estimates with confidence intervals;
  5. variables and strategy used for adjustment;
  6. the time horizon;
  7. a restrained interpretation tied to limitations.

Example template:

Among [population] followed for [time], [events/denominator] exposed participants and [events/denominator] comparison participants developed [outcome]. Standardized risks were [x] and [y], corresponding to an RD of [value] and RR of [value] (95% CI [lower, upper]). Estimates adjusted for [prespecified variables]. Residual confounding by [important factor] and [measurement/selection limitation] may remain.

15.2 Avoid common interpretation errors

Do not:

  • say “no association” merely because a confidence interval includes the null;
  • interpret an OR as a risk ratio when the outcome is common;
  • claim causation from adjustment alone;
  • infer subgroup differences from separate significance tests;
  • report only relative effects when absolute risk informs decisions;
  • treat administrative-code validity as universal across settings;
  • imply that more decimals mean more certainty;
  • generalize beyond the sampled setting without discussing transportability;
  • confuse statistical, clinical, and public-health importance.

15.3 Reporting guidelines

Use design-appropriate checklists as aids, not replacements for judgment:

  • STROBE for observational studies;
  • CONSORT for randomized trials;
  • PRISMA for systematic reviews;
  • STARD for diagnostic-accuracy studies;
  • TRIPOD for prediction models;
  • RECORD for routinely collected health data;
  • CHEERS for health economic evaluation.

16. Reproducibility checklist

Before release, confirm that:

  • the question, estimand, design, and analysis align;
  • raw data are preserved and provenance is recorded;
  • code runs from a clean session in a documented environment;
  • random seeds are set where random procedures are used;
  • denominators and exclusions can be reconstructed;
  • variable labels, units, and reference categories are explicit;
  • tables and figures are produced from code, not manual copy/paste;
  • analytic decisions and deviations are logged;
  • sensitive output is disclosure-reviewed;
  • software and package versions are captured;
  • null, unexpected, and adverse findings are retained;
  • reusable code excludes credentials and local personal paths.
sessionInfo()
## R version 4.6.1 (2026-06-24)
## Platform: aarch64-apple-darwin23
## Running under: macOS Tahoe 26.5.1
##
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.6/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1
##
## locale:
## [1] C.UTF-8/C.UTF-8/C.UTF-8/C/C.UTF-8/C.UTF-8
##
## time zone: America/Edmonton
## tzcode source: internal
##
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base
##
## other attached packages:
## [1] survival_3.8-6
##
## loaded via a namespace (and not attached):
##  [1] digest_0.6.39   R6_2.6.1        fastmap_1.2.0   Matrix_1.7-5    xfun_0.60
##  [6] lattice_0.22-9  splines_4.6.1   cachem_1.1.0    knitr_1.51      htmltools_0.5.9
## [11] rmarkdown_2.31  lifecycle_1.0.5 cli_3.6.6       grid_4.6.1      sass_0.4.10
## [16] jquerylib_0.1.4 compiler_4.6.1  tools_4.6.1     evaluate_1.0.5  bslib_0.12.0
## [21] yaml_2.3.12     rlang_1.3.0     jsonlite_2.0.0

17. Exercises

Exercise 1: Frequency measures

A town has 20,000 residents. On January 1, 1,000 have a chronic condition. During the year, 380 new cases occur among those initially free of the condition. They contribute 18,500 person-years at risk.

  1. Calculate point prevalence on January 1.
  2. Calculate one-year cumulative incidence.
  3. Calculate the incidence rate per 1,000 person-years.
Solution
prevalence_ex1 <- 1000 / 20000
risk_ex1 <- 380 / (20000 - 1000)
rate_ex1 <- 380 / 18500 * 1000
c(prevalence = prevalence_ex1,
  one_year_risk = risk_ex1,
  incidence_per_1000_person_years = rate_ex1)
##                      prevalence                   one_year_risk
##                            0.05                            0.02
## incidence_per_1000_person_years
##                           20.54

The results are 5% prevalence, 2% one-year risk, and about 20.5 cases per 1,000 person-years.

Exercise 2: Association and impact

In a cohort, 120 of 1,500 exposed people and 60 of 1,500 unexposed people develop an outcome.

  1. Build the 2 x 2 table.
  2. Calculate RR, OR, and RD.
  3. Explain why RR and OR differ.
Solution
exercise_tab <- matrix(c(120, 1380,
                         60, 1440), nrow = 2, byrow = TRUE)
epi_2x2(exercise_tab)

Risk is 8% versus 4%, so RR = 2 and RD = 4 percentage points. The OR is about 2.09 because it compares odds rather than risks. The outcome is uncommon enough that the two relative measures are fairly close, but they are not identical.

Exercise 3: Screening

A test has 95% sensitivity and 90% specificity. In a population of 10,000, disease prevalence is 1%.

  1. Calculate expected TP, FN, FP, and TN.
  2. Calculate PPV and NPV.
  3. Explain why most positive results may still be false positives.
Solution
population_ex3 <- 10000
cases_ex3 <- population_ex3 * 0.01
noncases_ex3 <- population_ex3 - cases_ex3
tp_ex3 <- cases_ex3 * 0.95
fn_ex3 <- cases_ex3 - tp_ex3
tn_ex3 <- noncases_ex3 * 0.90
fp_ex3 <- noncases_ex3 - tn_ex3
c(TP = tp_ex3, FN = fn_ex3, FP = fp_ex3, TN = tn_ex3)
##   TP   FN   FP   TN
##   95    5  990 8910
diagnostic_metrics(tp_ex3, fp_ex3, fn_ex3, tn_ex3)
## sensitivity specificity         PPV         NPV LR_positive LR_negative    accuracy
##     0.95000     0.90000     0.08756     0.99944     9.50000     0.05556     0.90050

There are many more noncases than cases. Even a 10% false-positive fraction applied to 9,900 noncases produces far more false positives than the 95 true positives.

Exercise 4: Study design

You need to study a very rare cancer with a 20-year latency and have access to archived occupational records. Which design is efficient, and what control-selection principle is essential?

Solution

A case-control study is efficient because investigators intentionally sample cases. If a well-defined workforce cohort exists, a nested case-control study may be especially strong. Controls must represent the exposure distribution of the source population that produced the cases and must be eligible to become cases at the relevant time.

Exercise 5: Bias and causal structure

A study of air pollution and asthma severity includes only people admitted to hospital. Both pollution exposure and asthma severity affect admission. What can happen when the analysis conditions on hospitalization?

Solution

Hospitalization is a common effect (collider) of exposure and severity. Restricting to hospitalized people can open a noncausal path between them, producing collider/selection bias. More covariate adjustment within the selected sample does not automatically fix the problem.

Exercise 6: Formulate a protocol question

Rewrite “Does exercise prevent dementia?” as a PECO question. Identify at least two likely confounders and one measurement challenge.

Example solution

Among community-dwelling adults aged 60–75 without dementia at baseline (P), what is the 10-year dementia risk under at least 150 minutes/week of moderate-to-vigorous physical activity (E) compared with less than 30 minutes/week (C), with dementia defined by adjudicated clinical criteria (O)? Age, education, vascular health, and baseline cognition are plausible confounders. Activity may be misclassified by self-report and may decline because of prodromal dementia, creating reverse-causation concerns. Repeated accelerometer measurement and a lag analysis could address parts of these problems.

18. Glossary

Term Brief definition
Absolute risk Probability of an outcome over a stated interval
Attack rate Cumulative incidence during an outbreak
Bias Systematic error in estimating a target quantity
Case definition Standard criteria for classifying an outbreak/surveillance case
Censoring Event time is only partially observed
Collider Variable caused by two other variables; conditioning can induce association
Confounder Cause/predictor that creates a noncausal exposure-outcome comparison
Consistency Observed outcome under received exposure equals the corresponding defined potential outcome
Cumulative incidence Proportion initially at risk who develop an outcome in a stated period
DAG Directed acyclic graph representing assumed causal relationships
Effect modification Effect differs across levels of another variable on a specified scale
Exchangeability Compared groups are counterfactually comparable, possibly conditional on covariates
Incidence rate New events divided by person-time at risk
Interaction Departure from a specified additive or multiplicative effect model
Misclassification Measured category differs from the true category
Odds ratio Ratio of outcome odds between exposure groups, or exposure odds between case/control groups
Person-time Sum of eligible time contributed while at risk
Positivity Each covariate pattern has possible exposure to every compared strategy
Prevalence Proportion with a condition at a time or during a period
Risk difference Difference in outcome risks between groups
Risk ratio Ratio of outcome risks between groups
Selection bias Distortion caused by mechanisms determining observation/analysis
Sensitivity Probability of a positive test among truly diseased people
Specificity Probability of a negative test among truly nondiseased people
Standardization Averaging stratum-specific measures over a common distribution
Target population Population to which the desired inference applies
Time zero Aligned start of eligibility, assignment/exposure, and follow-up

19. Further reading and authoritative resources

Final takeaway

Epidemiology is not a collection of formulas. It is a disciplined way to connect a population question to a defensible design, accurate measurement, an appropriate comparison, transparent analysis, and action proportionate to the evidence. Begin with the question and time zero; keep denominators visible; report absolute and relative effects; distinguish prediction, association, and causation; and make uncertainty and assumptions part of the result.