Interactive R tutorials for clinical programmers transitioning from SAS to the pharmaverse ecosystem.
Each lesson ships as a self-contained learnr .Rmd file: learners run live R
code in the browser via Posit Connect, or locally in RStudio by clicking
Run Document. Every tutorial uses real clinical trial data from the
CDISCPILOT01 Alzheimer's / Xanomeline study (pharmaverseadam,
pharmaversesdtm) — no synthetic toy data.
| Author | Hamid Tavakoli |
| License | MIT |
| learnr tutorials | 46 .Rmd files · ~63,400 lines of R |
| Coding exercises | 712 live exercises (with hints & solutions) |
| Quiz questions | 168 multiple-choice questions |
| Lesson plan docs | 137 narrative .md files |
| Dataset | CDISCPILOT01 — pharmaverseadam + pharmaversesdtm |
The repo is locked with renv. Run the bootstrap script once to install every required package (pharmaverse, admiral, learnr, teal, etc.). Windows / macOS users get pre-built binaries from the Posit Public Package Manager — no Rtools / Xcode required.
# from a terminal, in the project root
Rscript setup.ROr from an R session opened in the project folder:
source("setup.R")The script:
- Checks you are on R >= 4.4.
- Points the session at P3M binaries.
- Installs/upgrades renv.
- Runs
renv::restore(prompt = FALSE). - Falls back to direct
install.packages()for the pharmaverse core ifrenv::restore()cannot resolve a package.
If setup.R reports missing packages, re-run it (transient network errors are
common on first install) or install them manually with install.packages().
# open any .Rmd in RStudio and click "Run Document", or:
rmarkdown::run("pharmaverse_tutorials/04_datastep_to_dplyr.Rmd")Posit Connect: publish any
.Rmdwithrsconnect::deployApp()for a hosted, shareable version.
- Real data only — all exercises use
pharmaverseadam::adsl/adae/adlb/advsandpharmaversesdtmdomain tables. Fabricated tibbles appear only when a concept has no real-data equivalent. - Mocked package infrastructure — every lesson contains an API-compatible
mock of the featured package in the
setupchunk, so exercises run in any environment without installing the package under study. - Progressive disclosure —
progressive: truekeeps sections hidden until the learner is ready;allow_skip: truelets advanced users jump ahead. - Exercise scaffolding — blanks shown as
___; every exercise has at least one hint chunk and a fully-worked solution chunk. - SAS↔R mapping — each lesson opens with an explicit SAS→R translation table or side-by-side comparison where relevant.
pharmaverse-tutorials/
│
├── README.md ← this file
├── CLAUDE.md ← AI-assisted development context
├── LICENSE.txt ← MIT License
│
├── pharmaverse_tutorials/ ← PRIMARY DELIVERABLE: 46 learnr .Rmd files
│
├── pharmaverse01/ ← Lesson plans 00–03 (4 .md + README)
├── pharmaverse02/ ← Lesson plans 04–06 (3 .md + README)
├── Pharmaverse03/ ← Lesson plans 07–11 (5 .md + README)
├── Pharmaverse04/ ← Lesson plans 12–15 (4 .md + README)
├── Pharmaverse05/ ← Lesson plans 16–19 (4 .md + README)
├── Pharmaverse06/ ← Lesson plans 20–24 (5 .md + README)
├── Pharmaverse07/ ← Lesson plans 25–32 (8 .md)
├── Pharmaverse08/ ← Lesson plans 33–37 (5 .md + README)
├── Pharmaverse09/ ← Lesson plans 38–42 (5 .md + README)
├── Pharmaverse10/ ← Lesson plans 43–48 (6 .md + README)
│
└── renv/ ← renv lockfile for reproducible packages
Each pharmaverseXX/ folder contains human-readable narrative lesson plans
(.md) used for curriculum planning and review. The .Rmd files in
pharmaverse_tutorials/ are the deployed interactive tutorials.
Lessons 00–03 ·
pharmaverse01/
Lesson plans
| File | Topic |
|---|---|
| 00_pharmaverse_overview.md | What is pharmaverse? Ecosystem map, CDISC context |
| 01_ars_ard_paradigm.md | ARS / ARD paradigm — from SAS macros to structured results |
| 02_environment_setup.md | renv, RStudio, Posit Connect, package management |
| 03_r_primer_part1_data_basics.md | R data types, vectors, data frames, tibbles |
Interactive tutorial
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 00 | 00_setup_and_orientation.Rmd | 3 | 1 | R environment, renv, RStudio orientation |
Lessons 04–06 ·
pharmaverse02/
Lesson plans
| File | Topic |
|---|---|
| 04_r_primer_part2_datastep_to_dplyr.md | DATA step → dplyr narrative curriculum |
| 05_r_primer_part3_joins_sql_functions.md | PROC SQL → dplyr joins and window functions |
| 06_r_primer_part4_tidyverse.md | tidyr, stringr, lubridate, purrr narrative |
Interactive tutorials
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 04 | 04_datastep_to_dplyr.Rmd | 56 | 3 | filter, select, mutate, summarise, group_by, lag/lead, across, cumulative functions, 2 capstones |
| 05 | 05_joins_sql_functions.Rmd | 20 | 4 | inner/left/anti/cross joins, SQL-style window functions |
| 06 | 06_tidyverse.Rmd | 29 | 7 | tidyr pivoting, stringr, lubridate, purrr |
Lessons 07–11 ·
Pharmaverse03/
Lesson plans
| File | Topic |
|---|---|
| 07_pharmaverseraw.md | pharmaversesdtm / pharmaverseadam raw dataset exploration |
| 08_sdtm_oak_part1_concepts.md | sdtm.oak concepts — hardcode, assign, condition |
| 09_sdtm_oak_part2_mapping.md | sdtm.oak conditional mapping, SUPP domains |
| 10_sdtm_oak_part3_supp_relrec.md | sdtm.oak RELREC, define-XML with xportr |
| 11_sdtmchecks.md | sdtmchecks, Pinnacle 21 rule categories |
Interactive tutorials
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 07 | 07_pharmaverseraw.Rmd | 20 | 6 | Domain inventory, variable metadata, CDISC structure exploration |
| 08 | 08_sdtm_oak_part1.Rmd | 21 | 9 | sdtm.oak — hardcode_ct(), assign_ct(), assign_no_ct() |
| 09 | 09_sdtm_oak_part2.Rmd | 16 | 4 | Conditional mapping, SUPP domain construction |
| 10 | 10_sdtm_oak_part3.Rmd | 12 | 7 | RELREC, define-XML generation |
| 11 | 11_sdtmchecks.Rmd | 15 | 5 | sdtmchecks validation functions, Pinnacle 21 rule mapping |
Lessons 12–15 ·
Pharmaverse04/
Lesson plans
| File | Topic |
|---|---|
| 12_metacore.md | metacore — specs objects, variable metadata |
| 13_metatools.md | metatools — dataset derivation helpers |
| 14_admiral_part1_foundations.md | admiral foundations — templates, derivation functions |
| 15_admiral_part2_adsl.md | admiral ADSL derivation walkthrough |
Interactive tutorials
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 12 | 12_metacore.Rmd | 12 | 5 | metacore specs, variable/value metadata, validation |
| 13 | 13_metatools.Rmd | 12 | 3 | metatools — check_ct_data(), combine_supp(), build datasets |
| 14 | 14_admiral_part1.Rmd | 9 | 5 | admiral templates, derive_vars_*(), date imputation |
| 15 | 15_admiral_part2_adsl.Rmd | 11 | 5 | ADSL: treatment dates, population flags, disposition |
Lessons 16–19 ·
Pharmaverse05/
Lesson plans
| File | Topic |
|---|---|
| 16_admiral_part3_bds.md | BDS datasets (ADLB, ADVS) |
| 17_admiral_part4_occds.md | OCCDS datasets (ADAE) |
| 18_admiral_part5_adtte.md | ADTTE / time-to-event |
| 19_admiral_part6_advanced.md | Advanced patterns, custom derivations, extensions |
Interactive tutorials
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 16 | 16_admiral_part3_bds.Rmd | 13 | 7 | ADLB/ADVS: analysis records, baseline, toxicity grades |
| 17 | 17_admiral_part4_occds.Rmd | 9 | 8 | ADAE: treatment-emergent flags, severity, seriousness |
| 18 | 18_admiral_part5_adtte.Rmd | 7 | 7 | ADTTE: derive_param_tte(), Kaplan-Meier inputs |
| 19 | 19_admiral_part6_advanced.Rmd | 8 | 8 | Custom derivation functions, admiral extensions pattern |
Lessons 20–24 ·
Pharmaverse06/
Lesson plans
| File | Topic |
|---|---|
| 20_admiralonco.md | admiralonco — oncology ADaM (ADRS, ADTR, ADTTE) |
| 21_admiralvaccine.md | admiralvaccine — immunogenicity, reactogenicity |
| 22_admiralophtha.md | admiralophtha — ophthalmology endpoints (VA, IOP) |
| 23_admiralpeds.md | admiralpeds — paediatric growth metrics, z-scores |
| 24_admiralmetabolic.md | Metabolic syndrome composite endpoints |
Interactive tutorials
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 20 | 20_admiralonco.Rmd | 21 | 7 | ADRS (response), ADTR (tumour), BICR vs investigator |
| 21 | 21_admiralvaccine.Rmd | 20 | 6 | ADIS (immunogenicity), ADCE (reactogenicity), titre analysis |
| 22 | 22_admiralophtha.Rmd | 18 | 6 | Visual acuity letter scores, IOP, BCVA analysis sets |
| 23 | 23_admiralpeds.Rmd | 20 | 5 | WHO growth charts, z-scores, age-adjusted endpoints |
| 24 | 24_admiralmetabolic.Rmd | 23 | 4 | Metabolic composite flags, HbA1c, HOMA-IR |
Lessons 25–32 ·
Pharmaverse07/
Lesson plans
| File | Topic |
|---|---|
| 25_cards_part1_ard_concepts.md | cards — ARD concepts, ard_continuous(), ard_categorical() |
| 26_cards_part2_clinical_ards.md | cards clinical ARDs — safety, efficacy summaries |
| 27_cardx.md | cardx — ard_ttest(), ard_wilcoxtest(), ard_chisqtest() |
| 28_gtsummary_part1_basics.md | gtsummary basics — tbl_summary(), add_p() |
| 29_gtsummary_part2_clinical_patterns.md | gtsummary clinical patterns — tbl_merge(), themes |
| 30_cardinal_part1_overview.md | cardinal overview — freq_table(), cont_table() |
| 31_cardinal_part2_fda_safety.md | cardinal FDA safety tables |
| 32_tfrmt.md | tfrmt — formatting templates, frmt_combine(), body_plan() |
Interactive tutorials
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 25 | 25_cards_cardx.Rmd | 21 | 3 | ARD construction with cards/cardx, statistical test results |
| 26 | 26_gtsummary_part1.Rmd | 11 | 2 | tbl_summary(), by-arm demographics, add_n/add_p |
| 27 | 27_gtsummary_part2.Rmd | 9 | 2 | tbl_regression(), tbl_merge(), custom themes |
| 28 | 28_cardinal.Rmd | 14 | 2 | cardinal frequency and continuous summary tables |
| 29 | 29_tfrmt_part1.Rmd | 19 | 3 | tfrmt body_plan, frmt(), frmt_combine(), frmt_when() |
| 30 | 30_tfrmt_part2.Rmd | 16 | 2 | Spanning headers, row groups, footnotes, col_plan() |
| 31 | 31_gt.Rmd | 20 | 3 | gt table styling, colours, cell annotations |
| 32 | 32_tlf_capstone.Rmd | 14 | 4 | End-to-end ARD → formatted submission table capstone |
Lessons 33–37 ·
Pharmaverse08/
Lesson plans
| File | Topic |
|---|---|
| 33_rtables.md | rtables — split-based table structure |
| 34_tern.md | tern — clinical summary functions on rtables |
| 35_r2rtf.md | r2rtf — submission-ready RTF output |
| 36_Tplyr.md | Tplyr — count, shift, and descriptive table layers |
| 37_tidytlg.md | tidytlg — freq_table(), cont_table(), tlg_output() pipeline |
Interactive tutorials
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 33 | 33_rtables.Rmd | 16 | 1 | rtables split/table structure, row/col splits, pagination |
| 34 | 34_tern.Rmd | 14 | 1 | tern clinical functions (count_occurrences, summarize_vars) |
| 35 | 35_r2rtf.Rmd | 13 | 1 | rtf_body/title/footnote/page pipeline, multi-page tables |
| 36 | 36_Tplyr.Rmd | 18 | 2 | Tplyr layers (count, desc, shift), custom headers |
| 37 | 37_tidytlg.Rmd | 27 | 3 | tidytlg pipeline from summary stats to submission RTF |
Lessons 38–42 ·
Pharmaverse09/
Lesson plans
| File | Topic |
|---|---|
| 38_shiny_foundations.md | Shiny reactivity, modules, clinical app patterns |
| 39_teal_architecture.md | teal architecture — cdisc_data, teal_slice, tab_group |
| 40_teal_modules_general.md | Custom teal module authoring — UI/server pattern |
| 41_teal_modules_clinical.md | teal data layer — teal_data(), join_keys(), connectors |
| 42_teal_custom_deployment_validation.md | teal deployment, validation, testServer() |
Interactive tutorials
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 38 | 38_shiny_foundations.Rmd | 38 | 0 | reactiveVal, observe, modules, clinical UI patterns |
| 39 | 39_teal_architecture.Rmd | 7 | 4 | cdisc_dataset/cdisc_data, teal_slice filters, modules/tab_group |
| 40 | 40_teal_modules.Rmd | 6 | 2 | teal_module(), ui_args/server_args, qenv, testServer() |
| 41 | 41_teal_data_deployment.Rmd | 6 | 1 | teal_data(), join_keys(), dataset_connector(), Posit Connect |
| 42 | 42_teal_capstone.Rmd | 10 | 0 | Full CDISCPILOT01 4-module clinical data review app + debug challenge |
Lessons 43–48 ·
Pharmaverse10/
Lesson plans
| File | Topic |
|---|---|
| 43_xportr.md | xportr — XPT pipeline, date handling, metacore integration |
| 44_datasetjson.md | Dataset-JSON v1.1 spec, write/read, validation |
| 45_logrx.md | logrx — GxP logging, axecute(), batch execution |
| 46_diffdf_riskmetric.md | diffdf QC + riskmetric package risk scoring |
| 47_capstone_part1_data_pipeline.md | Capstone Part 1 — SDTM → ADaM pipeline design |
| 48_capstone_part2_deliverables.md | Capstone Part 2 — ADaM → TLF → submission package |
Interactive tutorials
| # | File | Exercises | Quizzes | Topic |
|---|---|---|---|---|
| 43 | 43_xportr.Rmd | 12 | 2 | xportr_type/label/length/format/order, unified xportr(), date encoding |
| 44 | 44_datasetjson.Rmd | 9 | 2 | dataset_json(), write/read, NA handling, round-trip fidelity |
| 45 | 45_logrx.Rmd | 8 | 2 | axecute(), log structure, warning triage, CI/CD integration |
| 46 | 46_diffdf_riskmetric.Rmd | 9 | 1 | diffdf() double-programming QC, riskmetric risk tier scoring |
| 47 | 47_capstone_part1.Rmd | 12 | 0 | SDTM→ADaM: ADSL (DM+EX+DS), ADAE derivation, XPT export |
| 48 | 48_capstone_part2.Rmd | 8 | 3 | ADaM→TLF→submission: gtsummary+tfrmt+r2rtf, logrx, diffdf, dual export |
# Core tidyverse + learnr
install.packages(c(
"learnr", "dplyr", "tidyr", "tibble", "stringr",
"purrr", "lubridate", "ggplot2"
))
# CDISC clinical data (open-source, CDISCPILOT01 study)
install.packages(c("pharmaverseadam", "pharmaversesdtm"))
# Packages covered lesson-by-lesson (install as needed)
install.packages(c(
# SDTM
"sdtm.oak", "sdtmchecks",
# Metadata
"metacore", "metatools",
# ADaM
"admiral", "admiralonco", "admiralvaccine",
"admiralophtha", "admiralpeds",
# ARD / TLF
"cards", "cardx", "gtsummary", "cardinal",
"tfrmt", "gt", "rtables", "tern",
"r2rtf", "Tplyr", "tidytlg",
# Shiny / teal
"shiny", "teal", "teal.data", "teal.modules.clinical",
# Submission
"xportr", "datasetjson", "logrx", "diffdf", "riskmetric"
))| Metric | Count |
|---|---|
learnr .Rmd tutorials |
46 |
Source lines (all .Rmd) |
~63,400 |
| Coding exercises | 712 |
| Multiple-choice quiz questions | 168 |
Narrative lesson plan .md files |
137 |
| Pharmaverse packages covered | 30+ |
48 lessons · 10 modules · from raw SDTM domains to a complete eCTD submission package