SPPH604-2026W

MASLD × BMI/WHtR — Reproduction (NHANES 2007–2018)

Scope note. These materials document a teaching reproduction of published analyses using the specified public data and course implementation. Differences from published results are reproducibility findings, not allegations of research misconduct, and may reflect analytic, implementation, or data-version differences. The findings below stand as recorded; this note frames how to read them, not whether they hold.

Fully reproducible re-analysis of Kueh MTW et al., BMJ Open 2026;16:e113719 (“Body weight categories and fat distribution in relation to all-cause mortality among adults with MASLD”). Built as the worked SPPH 604 example: replicate a recent open-data paper end-to-end from raw public data, then interrogate it.

Result: Table 1, Table 2, Figure 1 and panel (a) of Figure 2 (BMI) reproduce closely, though not exactly. Panel (b) of Figure 2 (WHtR) does not reproduce at the upper tail. See reproduction_report.md for the side-by-side comparison and the P1–P5 teaching map.

Looking up a variable? VARIABLE_MAP.md is the crosswalk: every variable this pipeline touches, which component file it lives in, which cycles actually contain it, whether a 77-looking value is a reserved code or a real measurement, a link to the CDC codebook anchored at that variable, and the line of our code that reads it. Generated from the raw .xpt files by R/07_variable_map.R, so it cannot drift.

Building a cohort from a paper? COHORT_BUILD_STEPS.md is the recipe: every step from download to masld_analytic.rds, and for each one the paper’s own sentence, the component and variables it forces you to read, the judgment call we had to make, and the N it cost. Read it before P1.

New here? WALKTHROUGH.md is the tour: what each script decides, the sample funnel, and the two places NHANES will mislead you. This file is the reference.

How to run

Requires R (≥ 4.4) with: haven, dplyr, tidyr, readr, purrr, survival, survminer, rms, ggplot2, patchwork, knitr, kableExtra, nhanesA.

source("R/run_all.R")     # builds everything; no paths to edit

The project root is detected automatically, so the folder can be unzipped anywhere. If data/raw/ is bundled (~204 MB of NHANES + mortality files), the pipeline runs offline: 01_download.R skips any file already present. If it is not bundled, the first run downloads those files from CDC and subsequent runs read from data/raw/.

Folder layout

reproduction/
├── README.md                    <- this file
├── reproduction_report.md       <- reproduced vs published, findings, P1–P5 map
├── COHORT_BUILD_STEPS.md         <- step-by-step recipe: paper sentence -> variables -> decision -> N
├── VARIABLE_MAP.md              <- generated crosswalk: variable -> file -> codebook -> our code
├── R/
│   ├── 00_setup.R               <- paths, cycles, component list
│   ├── 01_download.R            <- download raw NHANES + linked mortality
│   ├── 02_build_analytic.R      <- merge, FLI, MASLD, groups, mortality  (the core)
│   ├── 03_table1.R              <- Table 1 (baseline characteristics)
│   ├── 04_table2_cox.R          <- Table 2 (Cox regression)
│   ├── 05_figure1_km.R          <- Figure 1 (Kaplan–Meier)
│   ├── 06_figure2_rcs.R         <- Figure 2 (restricted cubic splines)
│   └── run_all.R                <- run everything in order
├── data/                        <- not in this repository; 01_download.R creates it
│   ├── raw/                     <- untouched downloads (saved for auditability)
│   │   ├── 2007-2008/ … 2017-2018/   (18 XPT components per cycle)
│   │   ├── mortality/           (6 public-use linked-mortality .dat files)
│   │   └── _download_manifest.csv    (URL / size / status of every file)
│   └── derived/
│       ├── masld_analytic.rds   <- the full analytic file (6,371 rows)
│       └── merged_all.rds       <- all-participant merged frame (pre-filter)
├── output/
│   ├── tables/  table1_reproduced.{csv,html}, table2_reproduced.csv
│   └── figures/ figure1_km.png, figure2_rcs.png
└── logs/                        <- run logs + sample_funnel.csv

Data provenance

Key definitions (see 02_build_analytic.R)

Caveats