Rows: 1,292
Columns: 13
$ patientunitstayid <dbl> 143870, 144815, 151179, 151900, 155961, 15630…
$ time_zero_offset <dbl> 7, 240, 15, 30, 312, 1188, 503, 292, 256, 231…
$ landmark_offset <dbl> 67, 300, 75, 90, 372, 1248, 563, 352, 316, 29…
$ early_vasopressor <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ first_vasopressor_offset <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ hospital_death <dbl> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ death_event <dbl> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
$ followup_days <dbl> 0.7993056, 0.5819444, 6.3868056, 4.3506944, 2…
$ age <dbl> 76, 34, 59, 66, 57, 87, 73, 39, 20, 18, 83, 8…
$ sex <chr> "Male", "Female", "Female", "Female", "Female…
$ baseline_map <dbl> 55, 61, 41, 53, 62, 61, 53, 56, 64, 64, 60, 6…
$ baseline_hr <dbl> 44, 76, 134, 86, 76, 80, 54, 86, 68, 74, 90, …
$ baseline_map_source <chr> "invasive", "cuff", "cuff", "cuff", "cuff", "…
Lab 1 — Constructing an Analytic Dataset for a Target Trial Emulation
EPID 785R · Regression and Study Design
Introduction
In lecture we saw that a randomized trial is specified through a protocol: eligibility criteria, treatment strategies, an assignment procedure, a time zero, outcomes, and a causal contrast. In a target trial emulation, none of these are given, so every one has to be reconstructed from data that were collected for other reasons.
This lab focuses on that reconstruction using a real data from the eICU Collaborative Research Database. We will use these data to answer:
Among adult ICU patients who develop hypotension, what is the effect of early vasopressor initiation versus no early vasopressor initiation on in-hospital mortality?
You will turn four raw tables from the de-identified multi-center ICU database into a single analytic dataset, while considering the components of the target-trial protocol. You will not estimate any causal effects. The dataset you construct here will serve as the raw material for later labs.
By the end you should be able to:
- specify a target trial using TARGET items 6a–6f;
- translate each protocol component into operations on longitudinal EHR data, and identify where the translation is imperfect;
- implement the translation as a transparent, checkable R pipeline;
- explain how a grace period in a treatment strategy threatens the alignment of eligibility, assignment, and follow-up
- identify what a landmark analysis does about problem 4, at what cost, and how cloning–censoring–weighting would handle it instead.
Deliverables: your completed R/ scripts, and this document rendered to HTML with your answers written in the answer blocks.
1 Before you start (~5 min)
- Open
lab1.Rprojin RStudio. - If you have never installed
pacman, runinstall.packages("pacman")once in the console. - Run
R/00_download_data.R. There’s nothing to complete in this file. It downloads four tables (~22 MB) from PhysioNet intodata/raw/and verifies their checksums. If PhysioNet is slow, use the data zip on CANVAS (unzip intodata/raw/, then re-run the script to verify).
The data. The eICU Collaborative Research Database Demo is an openly available sample of a large US multi-center ICU database: 2,520 ICU stays. We use four tables:
| table | rows | one row per | what we take from it |
|---|---|---|---|
patient |
2,520 | ICU stay | age, sex, ICU/hospital discharge times and statuses |
vitalPeriodic |
1.63M | vital-sign reading | invasive (arterial-line) MAP; heart rate |
vitalAperiodic |
274K | vital-sign reading | non-invasive (cuff) MAP |
infusiondrug |
38K | charted infusion rate | vasopressor infusions and their timing |
Codebook. Each table name above links to its page in the official eICU-CRD documentation (eicu.mit.edu) — the database’s codebook, with column-by-column definitions (the patient page, for instance, documents the "> 89" age masking you will handle in Step 1). The site also has a glossary of ICU and database terms and a browsable schema. It describes the full eICU-CRD; the demo is a subsample with identical structure, so everything applies as-is.
One convention: all times are “offsets” represented as integer minutes relative to ICU unit admission (admission = 0; negative offsets are events before ICU arrival, e.g., in the emergency department). There are no calendar dates.
Clinical context, in three sentences. Mean arterial pressure (MAP) below ~65 mmHg is the conventional threshold for hypotension in critical care: below it, organ perfusion is threatened. Vasopressors — norepinephrine, epinephrine, phenylephrine, vasopressin, dopamine — are continuous infusions that raise blood pressure, and when to start them (immediately, or after trying fluids first) is the clinical question you are preparing to answer. Whether starting one early (within the first hour of hypotension) affects survival is the kind of question our target trial will seek to address.
2 The target trial, specified and emulated (~12 min)
Recall the two-step logic from lecture: (1) specify the protocol of the (hypothetical, pragmatic) randomized trial that would answer the question; (2) emulate each component with the observational data, as faithfully as the data allow. The TARGET statement (Cashin et al. 2025) gives the specification items 6a–6f and, side by side, their emulation counterparts 7a–7f.
Draft the middle column now — one or two concrete sentences per cell describing the trial you would run, with no thought of data limitations. Leave the right column (what the eICU tables let you actually do) mostly blank: you will fill it row by row as you build the pipeline — each section below ends by telling you which rows to update.
| TARGET item | Hypothetical target trial | eICU emulation |
|---|---|---|
| 6a Eligibility criteria | ||
| 6b Treatment strategies | ||
| 6c Assignment procedures | ||
| 6d Follow-up | ||
| 6e Outcome | ||
| 6f Causal contrast |
A tip that helps with every row: imagine standing in the ICU at the moment a patient first becomes hypotensive. Everything the trial does — check eligibility, randomize, start the follow-up clock — happens at that moment, using only information available at that moment. Whenever the emulation is forced to use information from after that moment, something important in the protocol has changed.
Noticing where that happens is an important part of this lab.
3 The pipeline at a glance (~3 min)
Each script operationalizes one protocol component and writes one clearly named file. This is deliberate: an emulation whose design decisions are scattered through one giant script is difficult to audit.
data/raw (4 tables)
|
01_eligibility.R TARGET 6a -> data/derived/01_eligible.csv
|
02_exposure.R TARGET 6b-c -> data/derived/02_exposure.csv
|
03_outcome.R TARGET 6d-e -> data/derived/03_outcome.csv
|
04_analytic_dataset.R -> data/derived/analytic_dataset.csv
|
05_qc.R -> console QC report
Scripts 01–03 and 05 contain TODO blocks with ??? placeholders — invalid code, so a script stops with an error until you complete it. Each script prints checkpoint counts (expect …) so you know immediately whether your code did what the protocol says.
4 Step 1 — Eligibility and time zero (TARGET 6a) (~12 min)
Open R/01_eligibility.R, read it top to bottom, and complete TODO (1a), (1b), (1c). Then run it. What it does, and why:
Who can be in the trial (TODO 1a). Adults (≥18) in their first ICU stay of the hospitalization. The first-stay rule makes each hospitalization contribute at most one trial entry — in the target trial, a patient is enrolled once, not once per ICU visit. (One more 6a criterion — no vasopressor use before time zero — must wait for Step 2, because it needs the cleaned infusion data. Protocol components and pipeline stages need not line up one-to-one; what matters is that every criterion is applied, and that you can say where.)
When they enter it (TODOs 1b, 1c). Enrollment happens at the first measured MAP below 65 mmHg during the ICU stay. That instant is this trial’s time zero: eligibility is assessed there, the strategies are defined relative to it, and follow-up is anchored to it. Two operationalization decisions deserve your attention:
- Two measurement sources. MAP is recorded invasively (arterial line,
vitalPeriodic) for only ~430 of 2,520 stays — the sickest patients, who are also mostly already on vasopressors. Cuff MAP (vitalAperiodic) covers nearly everyone else. Using the invasive source alone would quietly restrict the trial to the sickest sliver of the ICU (we tried: the final cohort drops from ~1,300 to ~200, with 5 early initiators). The measurement process itself is part of the emulation — TARGET item 7a asks you to report exactly this kind of mapping decision. - A plausibility window. The raw series contains MAP values of −45 and 353 mmHg — transducer flushes and cuff artifacts, not physiology. We keep 30–150 mmHg. Note what makes this defensible: it is a rule about measurement validity, fixed before looking at anyone’s outcome, applied identically to everyone.
Checkpoints: 2,111 adult first stays → 1,378 eligible stays with an index event.
Q1. What event defines eligibility in the hypothetical trial?
YOUR ANSWER:
Q2. What eICU data are being used to emulate that event?
YOUR ANSWER:
Update rows 6a (both columns) of your table before moving on.
5 Step 2 — Treatment strategies and classification (TARGET 6b–6c) (~12 min)
Open R/02_exposure.R and complete TODO (2a), (2b), (2c). Then run it.
The strategies (6b), stated precisely. (1) Early initiation: begin a vasopressor infusion within 60 minutes of time zero. (2) No early initiation: do not begin one within 60 minutes; later initiation, per usual care, is allowed. Two features of this wording matter. First, the 60-minute window is a grace period: the strategy says “within the hour,” not “at minute zero,” because instantaneous initiation is neither clinically realistic nor how such a trial would be run. TARGET item 6b explicitly asks for grace periods to be reported as part of the strategy. Keep the grace period in mind — it is the source of everything in Section 6. Second, a patient who initiates at minute 61, or hour 6, is following strategy (2). “No early initiation” is not “never treated” — write your 6b row accordingly.
Finding the treatment in the data (TODO 2a). drugname is free text: 31 spellings of our five agents in this demo alone — brand names, units, concentrations, stray casing. You will write one case-insensitive regular expression, against a provided test battery that includes two traps (Dobutamine, Nicardipine) that must not match. This is a small taste of a big truth: in emulation, “the treatment” is an algorithm you write, not a fact you look up — and TARGET item 7b asks you to report that algorithm.
New users only (TODO 2b). Seventy of the 1,378 eligible stays show a vasopressor infusion before their time zero. Neither strategy describes them — you cannot “initiate within the hour” or “withhold for an hour” a drug that is already running. In the target trial they would be screened out at enrollment; here they are excluded by a criterion that belongs to row 6a even though the code lives in this script. (Lecture connection: this is the trial-emulation counterpart of the new-user design, and skipping it invites prevalent-user bias.)
Classification is not assignment (6c) (TODO 2c). In the trial, a coin flip at time zero puts patients in arm (1) or arm (2), and — in expectation — the arms are exchangeable. In the emulation nobody assigns anything: we classify patients by what the infusion record shows they did. Whatever made a clinician start norepinephrine within the hour — deeper hypotension, faster deterioration, a bed in a better-staffed unit — travels with the classification. When you tabulate the analytic dataset in Step 5 you will see the footprint this leaves.
Checkpoint: 1,308 stays (70 prevalent users excluded).
Q3. What are the two treatment strategies?
YOUR ANSWER:
Q4. How would treatment assignment work in the hypothetical randomized trial?
YOUR ANSWER:
Q5. Why is observed treatment initiation not equivalent to randomized assignment?
YOUR ANSWER:
Update rows 6b and 6c of your table.
6 Step 3 — Alignment, the landmark, and outcomes (TARGET 6d–6e) (~10 min)
Do not open the script yet — the next four paragraphs are the reason this lab exists.
The problem. Our strategies are defined by behavior during the 60 minutes after time zero. So at time zero, we cannot yet know anyone’s group: early_vasopressor is computed from the patient’s future. Now suppose we nevertheless started mortality follow-up at time zero, with groups defined that way. Consider a patient who dies 30 minutes after becoming hypotensive, without an infusion. They are classified “no early initiation,” and their death lands in that arm’s column — though they never had the full hour in which initiating was possible. Meanwhile, anyone classified as an early initiator had to survive at least to their initiation time: between time zero and initiation, the “early” arm cannot die, by construction. That pre-initiation stretch is immortal time, and its hallmark is exactly this misalignment: follow-up begins at time zero, but assignment isn’t determined until up to an hour later. The lecture’s alignment rule — the moment observations are classified into a strategy should coincide with the moment follow-up begins — is violated, and the violation systematically flatters early initiation (its arm banks guaranteed-alive minutes; the other arm absorbs the earliest deaths).
The fix used in this lab: a 60-minute landmark. Push the start of follow-up to the end of the grace period. Concretely: (i) classify each patient using the window [t0, t0+60], exactly as you did in Step 2; (ii) keep only patients still alive and observable at the landmark t0+60; (iii) begin follow-up at the landmark. Now classification is complete before the first minute of follow-up: alignment is restored, at the landmark rather than at time zero.
What the fix costs. The trial we are emulating has quietly changed. Its eligibility now effectively includes “survived, in the ICU, 60 minutes past hypotension onset,” and its follow-up starts an hour later than the question’s natural time zero. The estimand’s population is 60-minute survivors — patients who die or leave in the first hour are outside it. In our data this is a small restriction (16 of 1,308 stays), but nothing guarantees that in general; a landmark at 24 hours, say, could discard the sickest patients wholesale and answer a much easier question than the one asked. “Observable” matters too, not just “alive”: a patient transferred out of the ICU at minute 40 has an incomplete classification window — infusions are only charted in the ICU — so “no initiation seen” would not mean “no initiation.”
The outcomes (6e). The primary outcome is in-hospital death, from the patient table’s discharge status (“Expired” vs “Alive”; a handful of blanks become NA — an unrecorded outcome is not a survivor). For later labs we also keep the time-to-event version: death_event, and follow-up time computed from the landmark,
followup_days = (hospitaldischargeoffset - landmark_offset) / 1440
with follow-up ending at hospital discharge, dead or alive. (Live discharge ends our ability to observe in-hospital death — we will have much more to say about what discharge-as-end-of-follow-up does to estimands when we reach censoring and survival analysis.) The original offsets stay in the dataset so any of these choices can be revisited.
Now open R/03_outcome.R, complete TODO (3a), (3b), (3c), and run it. Checkpoints: 1,292 stays at the landmark (16 excluded); 27 early initiators.
Q6. When does follow-up begin in our emulation?
YOUR ANSWER:
Q7. Why does it begin at the landmark rather than at the first hypotensive measurement?
YOUR ANSWER:
Q8. What ends follow-up?
YOUR ANSWER:
Update rows 6d and 6e — and revisit 6a: did the landmark change who the trial is about?
7 Step 4 — The analytic dataset (~5 min)
R/04_analytic_dataset.R is fully provided: it selects and orders the final columns and writes data/derived/analytic_dataset.csv. Run it, then read its header comment: every column is annotated with the protocol component it operationalizes. That traceability — column ↔︎ protocol item — is the standard your own emulations should meet.
8 Step 5 — Quality control (~10 min)
Open R/05_qc.R, complete TODO (5a), (5b), and run it. The report distinguishes invariants — things that must hold by construction, so a violation means a bug in your pipeline (uniqueness; 0/1 coding; no initiation before time zero; no early initiator initiating after the landmark; no nonpositive follow-up) — from reports — counts you must be able to explain, not necessarily eliminate. Expected results, so you can tell data quirks from bugs:
- Flow: 1,378 → 1,308 → 1,292 → 1,292. In a real report this becomes a participant flow diagram — TARGET item 8.
- Groups: 27 early initiators (2.1%) vs 1,265. Sit with that number: even in ICU data, initiation within the hour of first hypotension is rare. Rarity of a strategy is not just an inconvenience — it previews the positivity condition from lecture: contrasts involving strategies almost no one follows lean ever harder on assumptions and models.
- Outcome: 136 in-hospital deaths among 1,274 with a recorded status; 18 missing (blank discharge status, kept as
NA— decide-and-document beats silently dropping). - All invariants: 0 violations. If you see a FAIL, the bug is yours — go find it (this is why the pipeline is five small files, not one big one).
- Source-data note: 17 stays have hospital discharge recorded before ICU discharge — impossible on its face. EHR timestamps are entered by humans. We count and disclose; a real analysis would decide (and report) what to do with them.
- Missingness: 3 stays lack a heart rate within ±60 min of time zero; age and sex are complete.
One thing you will not find in the QC report: deaths broken down by exposure group. That contrast is an effect estimate in embryo, and this lab stops, deliberately, at the dataset.
9 A more rigorous alternative: cloning, censoring, weighting (~8 min)
The landmark solved the alignment problem by moving time zero. There is a solution that leaves time zero where the question put it — at hypotension onset — and it is worth understanding conceptually now, because it is the standard modern answer to grace periods. (Concept only: no equations, no implementation, not in this course’s labs.)
The key observation: during the grace period, a patient who has not yet initiated is compatible with both strategies. A patient 20 minutes past hypotension with no infusion could still end up following “early initiation” (start by minute 60) or “no early initiation” (don’t). Their data, so far, are consistent with both arms. Cloning–censoring–weighting (CCW) takes that observation literally:
- Clone. At time zero, give each eligible patient a copy in each arm they are compatible with. Follow-up for both clones starts at time zero — no landmark, no discarded first hour, no immortal time: assignment (of clones) and the start of follow-up coincide by construction.
- Censor. Watch each clone against its assigned strategy, and artificially censor it the moment the patient’s observed behavior deviates: the “early initiation” clone is censored at minute 61 if no infusion has started; the “no early initiation” clone is censored at the moment an infusion starts inside the hour. A patient who dies at minute 30 contributes that death to both arms — which is exactly right, since their data were compatible with both strategies when they died.
- Weight. Artificial censoring is informative: clones are censored because of what happened after time zero, so the survivors of each arm are a selected subset. Inverse-probability-of-censoring weights re-inflate the uncensored clones to stand in for the censored ones, under assumptions (and models) about the censoring process.
In TARGET’s terms: the grace period lives in 6b (it is part of the strategy definition); cloning is the 6c/7c answer to “how do you classify people into strategies that are indistinguishable at time zero?” (item 7c names it explicitly); and censoring-plus-weighting is what lets 6d keep follow-up starting at assignment. The trade against the landmark is clean:
| 60-min landmark (this lab) | CCW | |
|---|---|---|
| follow-up starts | t0 + 60 | t0 (the trial’s own time zero) |
| population | 60-minute survivors, observable in ICU | everyone eligible at hypotension onset |
| classification | once, from the observed window | clones assigned to both arms; censored on deviation |
| price | changed target population; discards first hour | artificial censoring; needs censoring models + weights |
Q9. Why does defining “treated” as initiation sometime during the next 60 minutes create a problem if follow-up begins immediately at hypotension?
YOUR ANSWER:
Q10. How would CCW address this differently from our landmark solution?
YOUR ANSWER:
10 Synthesis — the causal contrast (TARGET 6f) (~8 min)
Finalize your 6a–6f table — all twelve cells. Then state the estimand this dataset is built to support: the contrast in in-hospital mortality risk under the two strategies (as a risk difference and/or risk ratio), in the landmark population. In a full analysis, identifying it would additionally require the lecture’s three conditions — conditional exchangeability given baseline covariates (we kept age, sex, baseline_map, baseline_hr as a start; a real emulation would need far more), positivity (recall the 27), and consistency (the strategies you wrote in 6b are precise enough to make “the outcome under strategy (1)” well-defined — that precision was the point).
Q11. What two counterfactual treatment strategies are being compared?
YOUR ANSWER:
Q12. How does the landmark restriction change the population represented by that contrast?
YOUR ANSWER:
Q13. How would the target trial differ if CCW rather than landmarking were used to handle the grace period?
YOUR ANSWER:
The takeaway. Each piece of the R pipeline operationalizes a specific component of the target trial — eligibility, strategies, classification, follow-up, outcome — and seemingly simple choices about treatment timing determine whether eligibility, assignment, and follow-up are properly aligned. When you read (or run) an observational study, the first questions to ask are the ones this lab made you answer with code: when is time zero, what could be known at it, and does follow-up start there?
Where this dataset goes next: Lab 2 samples from this cohort by outcome (case-control designs); the survival weeks use death_event and followup_days to build risk curves, where live discharge, censoring, and competing events get their full treatment.
References
- Cashin AG, Hansford HJ, Hernán MA, et al. Transparent Reporting of Observational Studies Emulating a Target Trial — The TARGET Statement. JAMA. 2025;334(12):1084–1093.
- Hernán MA, Robins JM. Using Big Data to Emulate a Target Trial When a Randomized Trial Is Not Available. Am J Epidemiol. 2016;183(8):758–764.
- Hernán MA, Sauer BC, Hernández-Díaz S, Platt R, Shrier I. Specifying a target trial prevents immortal time bias and other self-inflicted injuries in observational analyses. J Clin Epidemiol. 2016;79:70–75.
- Hernán MA. How to estimate the effect of treatment duration on survival outcomes using observational data. BMJ. 2018;360:k182.
- Maringe C, Benitez Majano S, Exarchakou A, et al. Reflection on modern methods: trial emulation in the presence of immortal-time bias. Int J Epidemiol. 2020;49(5):1719–1729.
- Morgan CJ. Landmark analysis: A primer. J Nucl Cardiol. 2019;26(2):391–393.
- Permpikul C, Tongyoo S, Viarasilpa T, et al. Early Use of Norepinephrine in Septic Shock Resuscitation (CENSER). Am J Respir Crit Care Med. 2019;199(9):1097–1105.
- Pollard TJ, Johnson AEW, Raffa JD, Celi LA, Mark RG, Badawi O. The eICU Collaborative Research Database, a freely available multi-center database for critical care research. Sci Data. 2018;5:180178. Demo v2.0.1: PhysioNet, 2021, doi:10.13026/4mxk-na84 (ODbL).