Complete-Case Analysis
An analysis restricted to records with no missing values on any variable used by the model, discarding partially observed records; unbiased only under restrictive missingness mechanisms and generally less efficient than principled missing-data methods such as multiple imputation or weighting.
In plain language
Complete-case analysis is a way of handling missing data by simply keeping only the patients who have every piece of information the analysis needs and throwing the rest out. For example, if your study requires age, treatment, and BMI for each patient, anyone missing BMI is dropped entirely before any numbers are calculated. This approach is fast and requires no extra work, but it can quietly distort your results: if the patients who are missing data are systematically different from those who are not, the group you end up analyzing no longer looks like the original study population.
Core idea
A complete-case analysis (CCA) — also called listwise deletion — fits the target model using only the subset of records that have no missing value on any variable the analysis touches (outcome, exposure, and every covariate in the adjustment set). Records with even a single missing field are dropped entirely. It is the silent default of almost every regression routine: `lm`, `glm`, `coxph`, `PROC LOGISTIC`, and `statsmodels` all delete incomplete rows before estimating. The appeal is that it requires no extra modelling and yields valid standard errors for the analysis that was actually run; the danger is that "the analysis that was actually run" silently answers a question about the complete-case subpopulation, not the target population, whenever missingness is informative.
The missingness taxonomy that governs validity
Following Rubin's framework, data are Missing Completely At Random (MCAR) when the probability of being missing is independent of both observed and unobserved values; Missing At Random (MAR) when that probability depends only on observed data; and Missing Not At Random (MNAR) when it depends on the unobserved value itself. Under MCAR the complete cases are a simple random subsample, so CCA is unbiased for every estimand — it just throws away information and inflates variance. Under MAR, CCA is biased for descriptive quantities (means, prevalences) but can still be unbiased for regression coefficients in an important special case: when missingness, conditional on the covariates in the model, is independent of the outcome. This is the result that makes CCA defensible far more often than the blunt "valid only under MCAR" slogan suggests — if records are missing because of the covariate values themselves (e.g., a lab is ordered more often in sicker patients) but, given those covariates, missingness does not depend on the outcome, the fitted coefficients are consistent even though MAR (not MCAR) holds. Under MNAR, CCA is biased in general and no complete-data method recovers the truth without an explicit, untestable model for the missingness mechanism.
Pros, cons, and trade-offs
- vs multiple imputation (`multiple-imputation-longitudinal-rwe`): MI imputes plausible values under MAR and pools estimates across imputations (Rubin's rules), recovering the information in partially observed records and giving correct variance that accounts for imputation uncertainty. CCA discards that information. White & Carlin (2010) make the precise comparison: when missingness is in covariates and the coefficient-validity condition above holds, CCA and MI are both unbiased and CCA can even be more efficient than a poorly specified imputation model — but when missingness is in the outcome alone, or when auxiliary variables predictive of the missing values exist, MI is more efficient and more robust. Prefer CCA when the proportion missing is small, missingness is plausibly unrelated to the outcome given covariates, and no strong auxiliary predictors exist; prefer MI when missingness is substantial, auxiliaries are available, or descriptive (not just coefficient) targets matter. - vs inverse-probability weighting / IPCW (`inverse-probability-of-censoring-weighting-rwe`): Weighting upweights the observed complete cases by the inverse of their estimated probability of being complete, correcting MAR selection without imputing. It is semiparametric-efficient when the missingness model is correct and avoids modelling the full joint distribution. Prefer weighting when the missingness mechanism is easier to model than the outcome distribution (e.g., monotone dropout in longitudinal follow-up); the two can be combined (augmented IPW / doubly robust) for protection against misspecification of either model. - vs available-case / pairwise deletion: Available-case analysis uses all records that have the specific variables needed for each sub-computation (e.g., each pairwise correlation), so different estimates rest on different samples and a covariance matrix can fail to be positive definite. CCA at least keeps one coherent analytic sample. Neither solves informative missingness.
When to use
CCA is the honest, transparent default when (1) the fraction of records lost is small (a common rule of thumb is <5% with no obvious pattern, though this is not a guarantee), (2) the substantive interest is in a regression coefficient and missingness is plausibly independent of the outcome given the modelled covariates, and (3) there are no strong auxiliary variables that would let imputation recover information CCA throws away. It is also the right reference analysis to report alongside MI or weighting: agreement between CCA and a principled method is reassuring, and material disagreement is itself a diagnostic that missingness is informative. Always report the number and characteristics of the dropped records and compare the complete-case sample to the full eligible sample on baseline covariates.
When NOT to use — and when it is actively misleading or dangerous
- Substantial or patterned missingness analyzed silently. Letting the software delete 30% of rows without a word converts a population question into a complete-case-subpopulation question and routinely biases effect estimates; quoting the result as if it were the target estimand is the single most common and most dangerous misuse. - Missingness driven by the outcome. If a variable is missing because of the outcome (e.g., severity scores not recorded for patients who died early), CCA is biased even for coefficients and the bias points in an unpredictable direction. Switch to a method with an explicit missingness/censoring model. - Descriptive targets under MAR. Means, prevalences, and incidence among complete cases are biased under MAR even when coefficients are not; do not report a complete-case prevalence as a population prevalence. - Many covariates each with a little missing. With p covariates each 5% missing and missingness roughly independent across them, the complete-case fraction shrinks toward 0.95^p — a handful of variables can silently delete a third of the sample. Count the realized analytic N, not the eligible N.
Data-source operational depth
- Claims: Administrative variables (enrollment, dispensings, ICD/CPT codes) are rarely "missing" in the survey sense — a value is either present or genuinely absent (a procedure that did not occur). Where missingness bites is in linked or supplemental fields (lab results, BMI, smoking, race/ethnicity, income), which are present only for the subset with that data feed. A CCA that requires a lab value implicitly restricts to patients who were tested — a strongly selected, typically sicker, group — so the complete-case sample is not MCAR; document the testing/linkage selection explicitly. - EHR: Missingness is informatively present: labs and vitals are recorded because a clinician ordered them, so "missing" carries information about the patient and the encounter. CCA on EHR covariates almost never satisfies MCAR and frequently violates the coefficient-validity condition because ordering depends on the same clinical state that drives the outcome. Treat informative presence as a structural feature, not random missingness. - Registry: Core registry fields (stage, histology, adjudicated events) are typically near-complete by protocol, so CCA is more defensible for those; long-form questionnaire items and follow-up forms are where attrition and item non-response accumulate. Report completeness by field and by calendar year.
Interpreting the output
Consider the ten-patient cohort where BMI is missing for patients 2, 5, and 7 — all three older and all three had the outcome event. Complete-case analysis retains n = 7 (a 30% reduction in sample). In the complete-case subset the observed event rate is 2/7 ≈ 29%; in the full sample it is 5/10 = 50%. Mean age in the complete-case subset is 60.6 years versus 63.0 in the full sample.
(1) Formal statistical interpretation. The complete-case estimate is unbiased only if data are MCAR — that is, if missingness of BMI is independent of all other variables, observed and unobserved. The pattern here clearly violates MCAR: the three patients missing BMI are systematically older and had the event, meaning the complete-case subset is not a simple random sample of the full cohort. Under MAR — where missingness depends only on observed variables such as age — a correctly specified complete-case analysis of the outcome model can still be unbiased if age is included in the model; the SE is penalized by the 30% sample reduction. Under MNAR (missingness depends on the missing BMI itself), complete-case analysis is biased regardless of model specification.
(2) Practical interpretation for a decision-maker. Discarding the three missing-BMI patients cuts the observed event rate roughly in half (50% → 29%) and shifts the mean age downward — evidence of substantial selection bias in this small example. Reporting only the complete-case result without disclosing the missingness pattern and mechanism assumption would mislead reviewers about the true event burden. Document the fraction dropped, how completers differ from excluded patients, and which missingness mechanism (MCAR, MAR, or MNAR) the complete-case analysis assumes.
Worked example
Scenario
A researcher is studying whether a new blood-pressure drug reduces the risk of a cardiovascular event over one year. The analysis needs three variables for each patient: whether they received the drug (treatment), their age, and their BMI. BMI is the problem: it comes from a clinic measurement, and not all patients had a clinic visit where it was recorded. Sicker, older patients were more likely to visit the clinic and therefore more likely to have BMI on file. The researcher applies complete-case analysis, which automatically drops every patient with a missing BMI.
Dataset
Ten-patient cohort — the raw data before any analysis. BMI is blank for patients who never had it measured.
| patient_id | age | treatment | bmi | had_event |
|---|---|---|---|---|
| 1 | 58 | drug | 27.4 | |
| 2 | 63 | drug | 1 | |
| 3 | 71 | placebo | 31.2 | 1 |
| 4 | 55 | drug | 24.8 | |
| 5 | 69 | placebo | 1 | |
| 6 | 60 | drug | 29.1 | |
| 7 | 74 | placebo | 1 | |
| 8 | 52 | placebo | 22.6 | |
| 9 | 67 | drug | 30.5 | 1 |
| 10 | 61 | placebo | 26.3 |
Steps
Start with 10 patients. Identify which rows have a missing BMI: patients 2, 5, and 7 each have no BMI value recorded.
Complete-case analysis drops all three patients with missing BMI. The analytic sample shrinks from 10 to 7 patients.
Check who was dropped: patients 2, 5, and 7 have ages 63, 69, and 74 — all older than the group average. All three also had the event (had_event = 1). The remaining 7 patients have a mean age of 60.6 and an event rate of 2 out of 7 (29%).
Compare to the full 10-patient group: mean age was 63.0 and event rate was 5 out of 10 (50%). The complete-case sample is younger and has a lower event rate than the original cohort.
This difference is not random chance — the missingness was linked to older age, and older age was linked to having the event. Dropping those patients makes the drug look more effective and the population look healthier than it really is.
Result
Complete-case N = 7 (dropped 3 of 10 patients, 30% loss). Event rate in the complete-case sample = 2/7 = 29%, versus 5/10 = 50% in the full cohort. The 21 percentage-point gap is a bias introduced by dropping older, sicker patients whose BMI happened to be missing — a clear sign that missingness was not random (MCAR does not hold here).
Runnable example
python implementation
Demonstrate complete-case analysis explicitly and contrast it with the full eligible sample. We construct a small cohort where a covariate (a lab value) is Missing At Random conditional on age, then fit a logistic regression two ways: on all rows with the...
import numpy as np
import pandas as pd
import statsmodels.formula.api as smf
rng = np.random.default_rng(20240601)
n = 2000
# Synthetic cohort: outcome depends on age and a lab value.
age = rng.normal(65, 10, n)
lab = 0.5 * (age - 65) / 10 + rng.normal(0, 1, n) # standardized lab
logit = -1.0 + 0.04 * (age - 65) + 0.6 * lab
y = rng.binomial(1, 1 / (1 + np.exp(-logit)))
df = pd.DataFrame({"y": y, "age": age, "lab": lab})
# MAR: probability the lab is missing depends only on observed age (older -> more often tested,
# i.e., less often missing). Given age, missingness is independent of the outcome.
p_missing = 1 / (1 + np.exp(2.0 - 0.05 * (df["age"] - 65)))
df.loc[rng.random(n) < p_missing, "lab"] = np.nan
eligible_n = len(df)
cc = df.dropna(subset=["y", "age", "lab"]) # listwise deletion (CCA)
cc_n = len(cc)
print(f"eligible N = {eligible_n}; complete-case N = {cc_n}; "
f"complete-case fraction = {cc_n / eligible_n:.3f}")
# Complete-case logistic regression (the implicit default of glm on incomplete data).
cca_fit = smf.logit("y ~ age + lab", data=cc).fit(disp=0)
print(cca_fit.summary2().tables[1].loc[:, ["Coef.", "Std.Err.", "P>|z|"]])
# Diagnostic: compare complete-case sample to the full eligible sample on covariates.
print("\nMean age - eligible vs complete-case:",
round(df["age"].mean(), 2), round(cc["age"].mean(), 2))r implementation
Complete-case analysis in R via the (default) na.action = na.omit, made explicit. We simulate a cohort with a covariate Missing At Random given age, report the realized complete-case sample size and fraction, and fit the complete-case logistic model....
library(mice)
set.seed(20240601)
n <- 2000
age <- rnorm(n, 65, 10)
lab <- 0.5 * (age - 65) / 10 + rnorm(n)
logit <- -1.0 + 0.04 * (age - 65) + 0.6 * lab
y <- rbinom(n, 1, plogis(logit))
df <- data.frame(y = y, age = age, lab = lab)
# MAR: lab missing with probability depending only on observed age.
p_missing <- plogis(2.0 - 0.05 * (age - 65))
df$lab[runif(n) < p_missing] <- NA
# Document the missing-data pattern before deleting anything.
print(md.pattern(df, plot = FALSE))
cc <- df[complete.cases(df), ] # listwise deletion (complete-case analysis)
cat(sprintf("eligible N = %d; complete-case N = %d; fraction = %.3f\n",
nrow(df), nrow(cc), nrow(cc) / nrow(df)))
# Complete-case logistic regression; na.omit is the default but stated for clarity.
cca_fit <- glm(y ~ age + lab, data = cc, family = binomial(), na.action = na.omit)
print(summary(cca_fit)$coefficients)
# Diagnostic: covariate distribution, eligible vs complete-case.
cat("Mean age eligible vs complete-case:",
round(mean(df$age), 2), round(mean(cc$age), 2), "\n")