ADaM-based R pseudocode for every Table, Listing, and Figure in an early-phase clinical-pharmacology study — a complete separate set per study design, on the pharmaverse stack (dplyr/tidyr/rtables/ggplot2/emmeans/lme4).
R twin of ../sas_tlf_pseudocode/. The higher-level pharmaverse path (admiral for ADaM, tern for pre-built TLF layouts) is the production route; this library shows the underlying logic explicitly. R runs laptop-only per SOP.
Rscript on your PATH) · the pharmaverse-style packages each script library()s — dplyr, tidyr, stringr, purrr, tibble, rtables, ggplot2, emmeans, lme4, broom, broom.mixed (plus haven to read .xpt/.sas7bdat ADaM) · read access to your study's ADaM datasets (ADSL, ADAE, ADLB, ADVS, ADEG, ADPC, ADPP, ADPD, ADIS, ADEX), CDISC-conformant · about 5 minutes to point one script at your data. No internet needed once the packages are installed. These are illustrative pseudocode skeletons: setup() defaults to placeholder paths (/data/adam) and assumes ADaM frames are loaded as tibbles — you wire in your real read step before a script produces output.Each script source()s 00_setup_helpers.R (it expects to be run with the design folder as the working directory, e.g. parallel/), calls setup(), gets dv <- design_vars("<DESIGN>"), then builds one TLF. Install the packages once, then Rscript a program.
① install packages (once) · ② point setup() / your read step at your ADaM · ③ Rscript the program from inside its design folder.
① Install the packages once (CRAN; needs internet for this step only):
Rscript -e 'install.packages(c("dplyr","tidyr","stringr","purrr","tibble","rtables","ggplot2","emmeans","lme4","broom","broom.mixed","haven"))'
② Run a program — cd into the design folder first so the relative source("../00_setup_helpers.R") resolves, then:
cd parallel
Rscript t_demographics.R
Quick-start checklist — click each as you finish it:
Rscript --version works (R 4.2+ on your PATH)install.packages(...) line above)setup() / the read step so it loads your ADaM (e.g. haven::read_xpt) instead of the placeholder pathsparallel/, crossover/, single_sequence/, sad/, mad/) and the TLF script you needcd into that design folder, then Rscript <script>.RRscript as shipped. To confirm a script is syntactically intact without touching data, parse it without executing:
Rscript -e 'invisible(parse("parallel/t_demographics.R")); cat("parses OK\n")'dplyr/tidyr/purrr (derivation) · rtables (regulatory table layout) · ggplot2 (figures) · emmeans + lme4/nlme (mixed models / BE) · broom/broom.mixed (tidy model output).
| Folder | Design | Key analysis differences |
|---|---|---|
parallel/ | Parallel-group | Between-group; treatment = TRT01A/TRT01AN |
crossover/ | Crossover (2×2, Williams) | Within-participant; by APERIOD/TRTSEQP; BE/ANOVA = lmer + emmeans, GMR + 90% CI |
single_sequence/ | Single-/fixed-sequence (e.g. DDI) | By APERIOD; fixed order, no randomized sequence; ratio + 90% CI vs reference period |
sad/ | Single Ascending Dose | Parallel cohorts (dose = treatment); dose-proportionality (power model, lm) |
mad/ | Multiple Ascending Dose | Parallel cohorts, repeated dosing; accumulation ratio (Rac), steady-state assessment |
Design is wired via design_vars("...") in 00_setup_helpers.R (returns trtvar/trtnvar, seqvar/seqvarn, byperiod). Programs differ only where the statistics genuinely differ (PK comparison, by-period/by-sequence safety, dose escalation); safety Tables/Listings are structurally identical, re-pointed to the design's variables.
00_setup_helpers.R→
setup()→
dv <- design_vars("<DESIGN>")→
read ADaM→
derive (dplyr/tidyr)→
layout (rtables / ggplot2)→
one TLF output
t_disposition · t_demographics · t_baseline_characteristics · t_exposure · t_protocol_deviations · t_prior_con_meds · t_medical_history · l_disposition
t_ae_overview · t_ae_by_soc_pt · t_ae_by_severity · t_ae_by_relationship · t_ae_sae_death_withdrawal · l_ae · l_sae_death
t_lab_summary · t_lab_shift · t_lab_marked_abnormal · f_lab_lft_scatter · f_lab_change · l_lab_abnormal
t_vitals_summary · f_vitals_change · l_vitals · t_ecg_summary · t_ecg_qtc_categorical · f_qtc_change · l_ecg
t_pk_conc_summary · l_pk_conc · f_pk_conc_mean (linear+semilog) · f_pk_conc_individual · t_pk_param_summary · l_pk_param · f_pk_param_boxplot · design-specific t_dose_proportionality (SAD) · t_accumulation (MAD) · t_be_anova (crossover / single-seq)
t_pd_summary · f_pd_change · f_pkpd_overlay · l_pd
t_ada_summary · t_ada_impact_pk · l_ada
t_ table · l_ listing · f_ figure. One script → one output. Each script source()s 00_setup_helpers.R, calls setup(), gets dv <- design_vars("<DESIGN>"), then the TLF body.
geomean = exp(mean(log(x))), geocv = 100*sqrt(exp(var(log(x)))-1) — never exp(mean(raw)).n_distinct(USUBJID)), not event rows; % denominator = population N per column from bign().dv$seqvar/dv$seqvarn; period tables use dv$byperiod.!is.na(A1HI) etc.).Treatment TRT01A/TRT01AN (parallel) · TRTA/TRTAN+APERIOD/APERIODC+TRTSEQP/TRTSEQPN (crossover/seq); populations SAFFL/PKFL/ITTFL; analysis PARAMCD/AVAL/CHG/PCHG/BASE/AVISIT/ATPTN/ANRIND/BNRIND/A1HI/A1LO/R2ULN; AE TRTEMFL/AESOC/AEDECOD/AESEVN/AREL/AESER/AESDTH/AEACN; PK ADPC AVAL=conc, ADPP PARAMCD=Cmax/Tmax/AUClast/AUCinf/CL/Vz/Rac.
Complete: 217 TLF scripts across all five design folders + 00_setup_helpers.R. Built mirroring the SAS twin with all its QC fixes pre-applied, then re-QC'd (6 family reviewers → per-finding verification: 24 findings, 14 confirmed P0/P1 fixed, 0 false-positives), then a deterministic sweep. All 218 scripts parse under Rscript, design_vars() matches every folder, geometric PK stats compute on the log scale, AE/safety counts are distinct participants, single-sequence participant-level tables key on dv$seqvar, period tables denominate from a period-bearing source, exposure uses ADaM AVAL/TRTDURD/NDOSES (no *DTC arithmetic), and the library is free of eDISH/Hy's Law terminology.
| Symptom | Why | Fix |
|---|---|---|
Error in library(rtables) : there is no package called 'rtables' (or dplyr, emmeans, lme4…) |
The pharmaverse packages each script library()s aren't installed in this R library. |
Run the install.packages(...) line in Run it once. Needs internet for that step. Confirm with Rscript -e 'library(rtables)'. |
cannot open file '../00_setup_helpers.R': No such file or directory |
You ran the script from the wrong directory; the source("../00_setup_helpers.R") path is relative to the design folder. |
cd into the design folder (parallel/, crossover/, etc.) first, then Rscript <script>.R — so ../ points back at the shared helper. |
object 'adam' not found / object 'adsl' not found |
These are pseudocode skeletons: setup() uses placeholder paths and assumes the ADaM frames are already loaded as tibbles — nothing actually reads your data yet. |
Wire in your real read step (e.g. adsl <- haven::read_xpt(file.path(env$adam,"adsl.xpt"))) and point adam/out at your study's ADaM and output paths before expecting output. |
Table runs but every % / count looks wrong or empty |
Population flag or treatment variable doesn't match your ADaM, so bign() denominators or SAFFL=="Y" filters drop everything. |
Confirm your ADaM carries the variables the library relies on (SAFFL/PKFL/ITTFL, TRT01A/TRTA, USUBJID); for crossover/single-seq check design_vars() matches your APERIOD/TRTSEQP naming. |
Wrong design_vars() branch (e.g. crossover script keyed on TRT01A) |
The design_vars("<DESIGN>") argument in the script header doesn't match the folder you copied it from. |
Use the script from the matching design folder; the argument must be PARALLEL/CROSSOVER/SINGLESEQ/SAD/MAD for that folder. |
| Geometric mean / CV% looks identical to the arithmetic mean | A modified copy is computing exp(mean(raw)) instead of working on the log scale. |
Keep pkstats(): geomean = exp(mean(log(x))), geocv = 100*sqrt(exp(var(log(x)))-1); filter AVAL > 0 first. Tmax stays Median (Min, Max). |
boundary (singular) fit warning from t_be_anova (crossover / single-seq) |
lmer can't estimate a random effect (too few sequences/periods or a near-degenerate design) — expected on small or illustrative data. |
It's a warning, not a failure. On real BE data confirm the model spec against the SAP; the reported GMR + 90% CI still comes from the validated tool, not this skeleton. |
| Numbers from a script land in a regulatory deliverable | This library is illustrative pseudocode for spec writing / double-programming — it is not validated and never the reported source. | Reported and regulated numbers come only from validated tools (Phoenix WinNonlin, Pinnacle 21, EDC) per SOP. An LLM never sources a number. |
t_disposition.R
t_demographics.R
t_baseline_characteristics.R
t_exposure.R
t_protocol_deviations.R
t_prior_con_meds.R
t_medical_history.R
l_disposition.R
t_ae_overview.R
t_ae_by_soc_pt.R
t_ae_by_severity.R
t_ae_by_relationship.R
t_ae_sae_death_withdrawal.R
l_ae.R
l_sae_death.R
t_lab_summary.R
t_lab_shift.R
t_lab_marked_abnormal.R
f_lab_lft_scatter.R
f_lab_change.R
l_lab_abnormal.R
t_vitals_summary.R
f_vitals_change.R
l_vitals.R
t_ecg_summary.R
t_ecg_qtc_categorical.R
f_qtc_change.R
l_ecg.R
t_pk_conc_summary.R
l_pk_conc.R
f_pk_conc_mean.R
f_pk_conc_individual.R
t_pk_param_summary.R
l_pk_param.R
f_pk_param_boxplot.R
t_pd_summary.R
f_pd_change.R
f_pkpd_overlay.R
l_pd.R
t_ada_summary.R
t_ada_impact_pk.R
l_ada.R
t_disposition.R
t_demographics.R
t_baseline_characteristics.R
t_exposure.R
t_protocol_deviations.R
t_prior_con_meds.R
t_medical_history.R
l_disposition.R
t_ae_overview.R
t_ae_by_soc_pt.R
t_ae_by_severity.R
t_ae_by_relationship.R
t_ae_sae_death_withdrawal.R
l_ae.R
l_sae_death.R
t_lab_summary.R
t_lab_shift.R
t_lab_marked_abnormal.R
f_lab_lft_scatter.R
f_lab_change.R
l_lab_abnormal.R
t_vitals_summary.R
f_vitals_change.R
l_vitals.R
t_ecg_summary.R
t_ecg_qtc_categorical.R
f_qtc_change.R
l_ecg.R
t_pk_conc_summary.R
l_pk_conc.R
f_pk_conc_mean.R
f_pk_conc_individual.R
t_pk_param_summary.R
t_pk_param_by_period.R
l_pk_param.R
f_pk_param_boxplot.R
t_be_anova.Rlmer + emmeans, GMR + 90% CI
t_pd_summary.R
f_pd_change.R
f_pkpd_overlay.R
l_pd.R
t_ada_summary.R
t_ada_impact_pk.R
l_ada.R
t_disposition.R
t_demographics.R
t_baseline_characteristics.R
t_exposure.R
t_protocol_deviations.R
t_prior_con_meds.R
t_medical_history.R
l_disposition.R
t_ae_overview.R
t_ae_by_soc_pt.R
t_ae_by_severity.R
t_ae_by_relationship.R
t_ae_sae_death_withdrawal.R
l_ae.R
l_sae_death.R
t_lab_summary.R
t_lab_shift.R
t_lab_marked_abnormal.R
f_lab_lft_scatter.R
f_lab_change.R
l_lab_abnormal.R
t_vitals_summary.R
f_vitals_change.R
l_vitals.R
t_ecg_summary.R
t_ecg_qtc_categorical.R
f_qtc_change.R
l_ecg.R
t_pk_conc_summary.R
l_pk_conc.R
f_pk_conc_mean.R
f_pk_conc_individual.R
t_pk_param_summary.R
t_pk_param_by_period.R
l_pk_param.R
f_pk_param_boxplot.R
t_be_anova.Rratio + 90% CI vs reference period
t_pd_summary.R
f_pd_change.R
f_pkpd_overlay.R
l_pd.R
t_ada_summary.R
t_ada_impact_pk.R
l_ada.R
t_disposition.R
t_demographics.R
t_baseline_characteristics.R
t_exposure.R
t_protocol_deviations.R
t_prior_con_meds.R
t_medical_history.R
l_disposition.R
t_ae_overview.R
t_ae_by_soc_pt.R
t_ae_by_severity.R
t_ae_by_relationship.R
t_ae_sae_death_withdrawal.R
l_ae.R
l_sae_death.R
t_lab_summary.R
t_lab_shift.R
t_lab_marked_abnormal.R
f_lab_lft_scatter.R
f_lab_change.R
l_lab_abnormal.R
t_vitals_summary.R
f_vitals_change.R
l_vitals.R
t_ecg_summary.R
t_ecg_qtc_categorical.R
f_qtc_change.R
l_ecg.R
t_pk_conc_summary.R
l_pk_conc.R
f_pk_conc_mean.R
f_pk_conc_individual.R
t_pk_param_summary.R
l_pk_param.R
f_pk_param_boxplot.R
t_dose_proportionality.Rpower model, lm
t_pd_summary.R
f_pd_change.R
f_pkpd_overlay.R
l_pd.R
t_ada_summary.R
t_ada_impact_pk.R
l_ada.R
t_disposition.R
t_demographics.R
t_baseline_characteristics.R
t_exposure.R
t_protocol_deviations.R
t_prior_con_meds.R
t_medical_history.R
l_disposition.R
t_ae_overview.R
t_ae_by_soc_pt.R
t_ae_by_severity.R
t_ae_by_relationship.R
t_ae_sae_death_withdrawal.R
l_ae.R
l_sae_death.R
t_lab_summary.R
t_lab_shift.R
t_lab_marked_abnormal.R
f_lab_lft_scatter.R
f_lab_change.R
l_lab_abnormal.R
t_vitals_summary.R
f_vitals_change.R
l_vitals.R
t_ecg_summary.R
t_ecg_qtc_categorical.R
f_qtc_change.R
l_ecg.R
t_pk_conc_summary.R
l_pk_conc.R
f_pk_conc_mean.R
f_pk_conc_individual.R
t_pk_param_summary.R
l_pk_param.R
f_pk_param_boxplot.R
t_accumulation.Raccumulation ratio (Rac), steady state
t_dose_proportionality_ss.Rsteady-state dose proportionality
t_pd_summary.R
f_pd_change.R
f_pkpd_overlay.R
l_pd.R
t_ada_summary.R
t_ada_impact_pk.R
l_ada.R