SPPH 604 · Application of Advanced Epidemiological Methods
A cohort is the first result of an analysis.
Today we follow one study from a Methods paragraph to a dataset that can be analysed.
Week 2 gave you six questions. Today is Q2: who is the population, and how is eligibility operationalised?
| What it teaches | On which paper | |
|---|---|---|
| Tuesday (today) | the judgment — turning a prose eligibility paragraph into logic you can defend | MASLD (Kueh) |
| Thursday (L2) | the mechanics — multi-cycle download, mortality linkage, eligibility steps, analytic dataset | benzodiazepine / opioid |
| P1 | both, transferred | your locked paper |
Eligibility decisions are analysis choices. That is why they sit inside Q2, not in a housekeeping appendix.
Given a published Methods section, you should be able to:
The standard is a defensible audit trail, not an unexplained match to the paper.
| Step | Question |
|---|---|
| 0 | Which cycles, files and variables are needed? |
| 1 | Who meets the age rule? |
| 2 | Who has a computable Fatty Liver Index? |
| 3 | Who meets the metabolic dysfunction definition? |
| 4 | How is the alcohol exclusion implemented? |
| 5 | How are the four BMI and waist phenotypes defined? |
| 6 | How are covariates constructed? |
| 7–8 | How are mortality data linked, checked and saved? |
| Population | Here | Why it narrows |
|---|---|---|
| Target | adults with MASLD in the US | who we want to speak about |
| Source | NHANES 2007–2018 respondents | who was sampled |
| Analytic | survivors of every filter, with exposure and outcome measurable | who we can compute on |
Cycle
One two-year survey wave, such as 2011–2012
Component
A topic-specific file, such as demographics, body measurements or laboratory tests
Variable
A column inside a component, such as age or waist circumference
SEQN
The participant identifier used to join files
This reproduction combines six cycles from 2007–2008 through 2017–2018.
For each component:
SEQNdemo_all <- bind_rows(demo_E, demo_F, demo_G, demo_H, demo_I, demo_J)
dat <- left_join(demo_all, bmx_all, by = "SEQN")The join choice defines which people can remain in the analysis.
Padding an unavailable variable with NA allows the code to run, but two situations then look identical:
Example: RIDRETH3, which identifies non-Hispanic Asian participants, begins in 2011–2012. Earlier cycles cannot supply the same classification.
Check variable availability by cycle before interpreting an NA.
The paper states:
“The study inclusion criteria were participants aged >18 years with evidence of MASLD.”
The reproduction uses:
Because NHANES age is recorded in whole years:
age > 18 means age 19 and olderage >= 18 includes people aged exactly 18| Rule | Final N | Deaths | Mean age, SD |
|---|---|---|---|
| Published paper | 6,300 | 585 | 51.0, 16.6 |
| Reproduction with age ≥18 | 6,371 | 586 | 51.0, 16.6 |
| Reproduction with age >18 | 6,301 | 585 | 51.4, 16.3 |
Seventy reproduced participants are exactly 18 years old.
All reproduction rows are the full reconstruction row set (not the fasting-weight domain).
The strict rule matches N and deaths. The inclusive rule matches the age distribution.
# Paper, Methods: eligibility stated as "aged > 18 years"
d <- filter(d, age >= 18) # NOT what the sentence says — deliberate, and recordedfilter() back to the paper, and makes a divergence visible instead of invisibleWeek 2 put three age rules on one slide:
| Study | Rule | Means |
|---|---|---|
| Thursday’s lab (L2) | >= 20 |
20 and over |
| This paper, as printed | > 18 |
19 and over |
| Our reproduction | >= 18 |
18 and over |
NHANES age is an integer, so one variable yields three different studies.
The discipline is not to pick the right one. It is to record which one you used, so a reader can undo it. A reproduction that quietly adopts a different rule has destroyed its own evidence.
In this study, a participant must have:
NHANES does not provide one MASLD diagnosis column for these six cycles. The analyst constructs the case definition.
2017–2018 includes liver transient elastography, but no comparable liver-imaging measure spans all six cycles used by this paper.
\[ \mathrm{FLI}=100\frac{\exp(L)}{1+\exp(L)} \]
\[ L=0.953\ln(TG)+0.139(BMI)+0.718\ln(GGT)+0.053(waist)-15.745 \]
| Input | NHANES variable | Unit |
|---|---|---|
| Triglycerides (TG) | LBXTR |
mg/dL |
| Body mass index (BMI) | BMXBMI |
kg/m² |
| Gamma-glutamyl transferase (GGT) | LBXSGTSI |
U/L |
| Waist circumference | BMXWAIST |
cm |
Hold BMI at 28.5 kg/m², GGT at 30 U/L and waist at 99 cm:
| Triglycerides | FLI | Steatosis by this rule? |
|---|---|---|
| 150 mg/dL | 66.4 | Yes |
| 110 mg/dL | 59.5 | No |
The cut occurs at approximately 112.4 mg/dL for this profile.
A continuous score becomes a hard inclusion boundary.
Triglycerides come from a fasting laboratory subsample with its own weight, WTSAF2YR.
| Stage after age eligibility | N | Meaning |
|---|---|---|
| Positive fasting subsample weight | 14,962 | Design-valid fasting domain |
| All four FLI inputs available | 14,170 | 792 additional records lack an input |
Assignment to the fasting subsample is design-based. Participation, fasting compliance and laboratory nonresponse can still affect who has a positive weight and complete data.
| Full reconstruction | Fasting-weight domain | |
|---|---|---|
| FLI computable | 14,989 | 14,170 |
| Final mortality-linked N | 6,371 | 6,048 |
| Main use | Reproduce the paper-like analysis | Design-aware population analysis |
The 323-person difference is not an arithmetic error.
Every reported N should name its row set.
| Criterion | Operational rule |
|---|---|
| Adiposity | BMI ≥25, or waist >94 cm in men or >80 cm in women |
| Glycaemia | glucose ≥100, HbA1c ≥5.7%, diabetes diagnosis or treatment |
| Blood pressure | SBP ≥130, DBP ≥85 or treatment |
| Triglycerides | TG ≥150 or lipid-lowering treatment |
| HDL cholesterol | ≤40 in men or <50 in women |
The paper also mentions treatment targeting HDL. The supplied implementation has no separate variable for that clause.
Both have FLI-defined steatosis, but no operational cardiometabolic criterion:
| SEQN | BMI, waist | Glucose, HbA1c | BP | TG, HDL |
|---|---|---|---|---|
| 58194 | 22.2, 87.2 cm | 94, 5.6% | 120/67 | 108, 141 |
| 71217 | 24.9, 93.3 cm | 99, 5.0% | 109/62 | 135, 47 |
Therefore, the MASLD step changes 6,376 to 6,374 in the full reconstruction.
An unresolved criterion contributes no positive count. Check whether each NA is a structural skip, cycle absence, refusal or genuine missingness before interpreting it.
The paper excludes consumption above two drinks per day for men and one for women.
The sentence leaves three questions:
ALQ130 records drinks on drinking days, not average drinks per calendar day.
| Implementation | Removed | Final N |
|---|---|---|
Threshold ALQ130 directly |
2,063 | 4,308 |
| Frequency × quantity averaged per day | 427 | 5,944 |
| Alcohol exclusion switched off | 0 | 6,371 |
| Published paper | 6,300 |
Counts are the full reconstruction row set.
Among the tested alcohol implementations, switching the exclusion off comes closest to the published cohort. It does not prove what the authors implemented.
The remaining 71-person gap is unresolved: a strict age >18 reading gives 6,301 with 585 deaths, but the published mean age matches ≥18.
For ALQ130:
| Code | Meaning |
|---|---|
| 777 | Refused |
| 999 | Do not know |
Leaving these codes in reclassifies nine refused or don’t-know answers as extremely heavy drinkers.
Missing-value codes are variable-specific. Always check the codebook.
The pipeline still:
A visible switch preserves the unresolved question for the next analyst.
Which alcohol implementation would you defend, and what would you write in the Methods?
Obesity means BMI ≥30 kg/m², or ≥25 kg/m² for Asian participants. High central adiposity means waist-to-height ratio (WHtR) ≥0.6.
| WHtR <0.6 | WHtR ≥0.6 | |
|---|---|---|
| Obesity | Group I: 391 | Group II: 4,585 |
| No obesity | Group III: 787 | Group IV: 608 |
Counts are the full reconstruction row set (6,371).
The exposure shares BMI and waist inputs with FLI. M1 asks what that structural dependence does to interpretation.
RIDRETH3 supplies a separate non-Hispanic Asian category only from 2011–2012 onward.
In 2007–2010:
Seventeen early-cycle participants lie in the BMI range where Asian status could change their phenotype. Seventeen is an upper bound, not a known error count.
Methods: obesity uses BMI ≥30 kg/m², with the Asian-specific cut at 25.
Table headers: groups are labelled BMI ≥25 and BMI <25.
Published non-obesity medians: 27.6 and 28.8 kg/m².
Those medians cannot belong to groups defined entirely by BMI <25. Coding the general cut at 30 reproduces all four published group medians.
The table labels appear to be wrong; the Methods and reproduced distributions agree.
The paper says that comorbidity definitions were “previously described,” without giving the full operational rules in this article.
The reproduction must choose definitions for hypertension, diabetes, dyslipidaemia, chronic kidney disease and medication use.
Do not choose a definition because it makes Table 1 match. Record the rule first, then report the residual difference.
This problem returns in P2, when Table 1 and confounding variables are constructed.
The NCHS linked mortality files supply:
The reproduction uses PERMTH_EXM, months from the mobile examination centre visit, because BMI and waist were measured at that examination.
The paper does not state whether it used examination-based or interview-based follow-up.
| Step | Criterion | N | Kind |
|---|---|---|---|
| 0 | NHANES 2007–2018 | 59,842 | Source frame |
| 1 | Age ≥18 | 36,580 | Eligibility |
| 2 | Positive fasting weight | 14,962 | Design domain |
| 3 | FLI computable | 14,170 | Item missingness |
| 4 | FLI ≥60 | 6,052 | Target population |
| 5 | At least one criterion | 6,050 | Target population |
| 6 | Phenotype assigned | 6,050 | Classification check |
| 7 | Mortality linked | 6,048 | Outcome ascertainment |
| Stage | N |
|---|---|
| Age ≥18 | 36,580 |
| FLI computable | 14,989 |
| FLI ≥60 | 6,376 |
| At least one criterion | 6,374 |
| Phenotype assigned | 6,374 |
| Mortality linked | 6,371 |
This path best reproduces the paper’s ordinary analyses. It fuses fasting design and data availability at the FLI step, so it should not replace the design-aware funnel.
| What it demonstrates | |
|---|---|
| Matched N, undocumented coding | nothing — the match is unattributable |
| Mismatched N, traced to a named step | the reproduction worked |
A documented N you can defend beats a matched N you cannot.
| Decision or limitation | Consequence |
|---|---|
| Age ≥18 versus >18 | 70 participants; different published targets match |
| Alcohol exclusion switched off | 427 would leave under the frequency-weighted rule |
| Asian status unavailable in early cycles | At most 17 phenotype assignments could change |
| Full versus fasting-weight row set | 6,371 versus 6,048 |
| Examination versus interview clock | Paper does not specify the choice |
A decision without a quantified consequence is not fully documented.
The benzodiazepine, opioid and mortality lab repeats the same mechanics:
dat.mort <- rbind(mortality_cycles)
dat.nhanes <- rbind(nhanes_cycles)
dat <- merge(dat.mort, dat.nhanes, by = "SEQN", all = TRUE)Then it applies a numbered chain of eligibility rules.
Your task in L2: write N remaining, N removed and the reason for every step.
If you can only do it on MASLD, you have not learned it.
L2’s exposure has four levels, and the reference category is “Neither”:
dat6 <- subset(dat5, benzodiazepines == "Yes" | ssris == "Yes" | opioids == "Yes")
dat6$exposure <- relevel(dat6$exposure, ref = "Neither")A ratio without its referent means nothing — and in both studies the referent is not “healthy”.
| Increment | What this lecture contributes |
|---|---|
| P1 | Cohort code, decision ledger and typed funnel |
| P2 | Operational covariates and Table 1 |
| P3 | An interaction analysis not present in this reproduction |
| P4 | Fasting subsample weight, strata and primary sampling units |
| P5 | Complete-case losses on the paper’s Model 1 covariates (109 of 6,048 missing cancer status) |
M1 asks which threat matters most. M2 asks what reproduced and what did not. M3 asks you to defend the decisions person by person.
For each cohort step, write four lines:
Then label the consequence: eligibility, design, item missingness, target population or outcome ascertainment.
Be ready to show one person who enters or leaves because of your decision.
Kueh MTW, Intaran MAU, Goh R, et al. Body weight categories and fat distribution in relation to all-cause mortality among adults with metabolic dysfunction-associated steatotic liver disease: a population-based analysis of NHANES, 2007–2018. BMJ Open. 2026;16:e113719. https://doi.org/10.1136/bmjopen-2025-113719
Bedogni G, Bellentani S, Miglioli L, et al. The Fatty Liver Index: a simple and accurate predictor of hepatic steatosis in the general population. BMC Gastroenterology. 2006;6:33.
CDC/NCHS documentation:
| Component | Main contribution |
|---|---|
DEMO |
age, sex, race and ethnicity, poverty-income ratio, survey design |
BMX |
BMI, waist and height |
TRIGLY and BIOPRO |
triglycerides and GGT for FLI |
GLU, GHB, HDL |
metabolic criteria |
BPX, BPQ, DIQ |
blood pressure and treatment criteria |
ALQ |
alcohol sensitivity analysis |
| NCHS mortality files | status, cause and follow-up time |
| Definition | Cardiovascular deaths |
|---|---|
| Heart plus cerebrovascular causes | 185 |
| Heart causes only | 158 |
| Published Table 2 | 158 |
Our counts are the full reconstruction row set (6,371).
The saved analytic variable combines heart and cerebrovascular causes. The Table 2 script creates a separate heart-only outcome, which reproduces the published event total.
Do not reuse a derived outcome variable without checking its definition.
dat1 <- subset(dat, RIDAGEYR >= 20) # N = 43,793
dat2 <- subset(dat1, RIDSTATR == "int + mec exam") # N = 41,659
dat3 <- subset(dat2, TAKERX_INLASTMONTH %in% c("No", "Yes")) # N = 41,614
dat4 <- dat3[complete.cases(dat3$BPQ020), ] # N not recorded
dat5 <- subset(dat4, mortstat == 0 | (mortstat == 1 & permth_int > 12)) # N = 31,591
dat6 <- subset(dat5, benzodiazepines == "Yes" | ssris == "Yes" | opioids == "Yes") # N = 4,049dat1 |
dat2 |
dat3 |
dat4 |
dat5 |
dat6 |
|
|---|---|---|---|---|---|---|
| kind | ELIGIBILITY |
DESIGN |
MISSINGNESS |
MISSINGNESS |
ELIGIBILITY |
TARGET POPULATION |
dat4 prints no N. The complete-case steps are the ones that go uncounted — in this lab and in most papers| Ask | On this paper |
|---|---|
| Is the case definition operational? | mostly — FLI ≥ 60 is exact; “≥ 1 criterion” needs the five spelled out |
| Is every exclusion executable as written? | no — the alcohol criterion is not |
| Does the funnel’s arithmetic close? | not reported; we had to rebuild it |
| Is the analytic N stated and reproducible? | stated; reproducible only up to the above |
COHORT_BUILD_STEPS.mdVARIABLE_MAP.md02_build_analytic.R03_table1.R04_table2_cox.RThe cohort counts in this deck come from the supplied reproduction pipeline. They are reproduction results, not numbers reported by the paper unless explicitly labelled.