Author
Modified

August 30, 2026

NHANES case study — remaining work

Finish the no-static-tables conversion

code/tables.py builds a table from live data and returns markdown, so a change in svy shows up in the write-up instead of silently disagreeing with it. Eight are converted: file_metadata, source_contributions, recode_cost, prevalence, interval_methods, multimorbidity, weight_population, diabetes_by_weight.

Seven are still transcribed. Line numbers are as of 2026-08-30:

index.qmd Table Source for the live version
51 TL;DR summary code/validate.py — same figures as the two brief tables
586 Brief 508, obesity code/validate.py
608 Brief 511, hypertension code/validate.py
630 R agreement, indicators record by record code/compare_r.py
642 R agreement, worst relative differences code/compare_r.py
722 Crude vs age-standardized, by condition code/standardize.py
738 Age-adjusted comparison code/standardize.py

The R-agreement pair does not need R at render time. code/r_*.csv hold R’s outputs and are checked in, so the comparison is svy plus a CSV read — pure Python, no Rscript in the docs build. That is why those files are in the repo.

Neither tables.py nor its functions are called from index.qmd yet; the hidden setup block at the top builds sample but does not import tables. Wiring is a separate step from writing the builders, and none of the eight finished ones is live on the page.

Why this matters, concretely

The tabulate block at line 488 was found on 2026-08-30 to be three things wrong at once: the top rule was nine characters short, the CV column was missing entirely, and the separator was the wrong weight. The numbers were right. It had drifted a whole column behind the library with nobody noticing, because nothing executes it.

Both boxed blocks are #| eval: false with hand-pasted output. The data is in the repo — these could execute.

Verified working as of 2026-08-30

Both scripts run clean against svy at feat/contrasts-covariance:

  • validate.py — briefs 508, 511, 516 all reproduce at published precision. The n=6,081 vs published 6,084 gap is still there and still unexplained.
  • compare_r.py — every section agrees with R; worst figures are prevalence 2.8e-15, GLM coefficients 3.2e-09, odds ratios 1.8e-08.

Two figures in the index.qmd summary table were one digit stale against that run (prevalence 2.9e-15, odds ratios 1.9e-08) and were corrected. Converting the table would have caught it.

Back to top