5.9 KiB
5.9 KiB
Target Trial Emulation Learning Project
This project is for learning how to code and understand target trial emulation in R.
The main teaching example is an ICU septic shock study:
Among ICU patients with suspected septic shock at ICU admission, what is the effect of initiating vasopressors early versus not initiating vasopressors early on 28-day mortality?
How To Work With The User
- Teach by showing small code chunks that the user can type in manually.
- Explain each meaningful line of code before moving on.
- Add generous learner-focused comments, especially around R functions, function arguments, return values, and unfamiliar package functions.
- Include many small examples and REPL-style checkpoints with code, expected output, and interpretation.
- Keep report-style Quarto notebooks focused on rendered tables and interpretation unless the user asks for REPL-style checkpoints there.
- Teach the base R mechanics when a concept is new, then prefer readable tidyverse-style code for routine analysis.
- Make the smallest correct change when editing project files.
- Keep scripts and notebooks numbered so the learning sequence is obvious.
- Avoid over-abstraction early; build reusable primitives only after the concept is clear.
- When adding reusable code, explain what future project need it supports.
- When using external dependencies, prefer wrapping them behind project functions so the user learns stable primitives.
Code Style
- Use the native pipe
|>, not%>% - snake_case for all names
- Prefer explicit, teaching-oriented comments over terse production-style code while this remains a learning project.
- For reusable functions, include comments describing purpose, arguments, return value, and at least one example call.
- Prefer
vapplyoversapply; explicit return types - Use
cli::cli_*for messages, notmessage()/cat() - Prefer cleaner imports with grouped startup message suppression, for example
suppressPackageStartupMessages({ library(readr); library(dplyr) }). - Prefer
dplyrverbs for data manipulation when external dependencies are allowed. - Prefer
skimrfor quick data summaries. - Prefer
gtandgtsummaryfor clear analytic tables in notebooks and reports. - Style with
styler::style_pkg()before commits
Don'ts
- Don't modify
renv.lockby hand - Don't
setwd()— rely on the project root (here::here()) - Don't introduce new dependencies beyond the approved stack without asking
Stack
- R 4.4 managed by rig
- renv for dependency management; lockfile is source of truth
- targets for pipeline orchestration
- tidyverse, especially
dplyr, for routine data manipulation - ggplot2 for exploratory plots and visual diagnostics
- data.table for performance-oriented data manipulation when needed
- skimr for quick data summaries
- gt for presentation tables
- gtsummary for descriptive and model summary tables
- Quarto for reports
Dependency Preference
- The first scripts may remain base R to teach the underlying mechanics.
- Going forward, use
dplyr,tidyverse,skimr,gt, andgtsummarywhere they make the code clearer. - Keep base R explanations available when they help the user understand what the package code is doing.
- Do not add packages outside the approved stack without asking first.
Workflow Roles
- Put reusable logic in
R/functions. - Put reusable smoke checks or command-line workflows in
scripts/. - Put polished displays, interpretation, exploratory visualization, and rendered result tables in Quarto notebooks.
- Avoid CSV intermediates when functions can be called directly and reproducibly.
- Use
run_all.shas the lightweight end-to-end runner until the project is ready fortargets. - Keep rendered notebook reports in
outputs/reports/.
Learning Roadmap
- Choose ICU teaching scenario: early vasopressor strategy in septic shock.
- Simulate a simple ICU observational cohort.
- Define the target trial protocol explicitly.
- Estimate a naive observational association.
- Show why naive comparison can be biased.
- Align time zero and eligibility criteria.
- Introduce treatment assignment windows.
- Add censoring logic.
- Add inverse probability weighting from first principles.
- Refactor repeated logic into reusable project functions.
- Re-implement selected steps with external dependencies.
- Build wrapper functions around external dependency workflows.
- Add a targets pipeline.
- Add initial Quarto report for reproducible analysis.
Initial Target Trial Protocol
Clinical question:
Among ICU patients with suspected septic shock at ICU admission, what is the effect of starting vasopressors within 2 hours compared with not starting vasopressors within 2 hours on 28-day mortality?
Eligibility criteria:
- ICU admission.
- Suspected sepsis.
- Hypotension at baseline.
- Elevated lactate at baseline.
Time zero:
- ICU admission.
Treatment strategies:
- Early vasopressor strategy: start vasopressors within 2 hours of ICU admission.
- No early vasopressor strategy: do not start vasopressors within 2 hours of ICU admission.
Outcome:
- Death within 28 days.
Baseline confounders in the first simulated dataset:
- Age.
- Sex.
- SOFA score.
- Lactate.
- Mean arterial pressure.
Initial estimand:
- Risk difference in 28-day mortality.
- Risk ratio for 28-day mortality.
File Sequence
run_all.sh: run the key scripts and render all current notebooks.scripts/01_simulate_icu_data.R: simulate an ICU cohort in memory and print a quickskimrsummary.R/simulate_icu_cohort.R: first reusable simulation primitive.R/estimate_naive_vasopressor_mortality_effect.R: shared naive mortality-effect primitive used by notebook workflows.notebooks/01_target_trial_basics.qmd: report-style walkthrough of the target trial protocol and initial results.notebooks/02_explore_simulated_data.qmd: exploratory visual diagnostics for the simulated cohort.