← Methods repository
CONCEPTADVANCEDPYTHON · R · SAS5 citations

Biomarker-Defined Cohort (RWE)

A cohort design that restricts eligibility to patients with a specific molecular, genomic, laboratory, pathology, or companion-diagnostic result, with time zero and follow-up anchored to biomarker ascertainment to avoid immortal time and testing-selection bias.

Study Designbiomarker-defined-cohortprecision-medicineimmortal-time-biastesting-selectionclinicogenomiccompanion-diagnosticspecial-populations-methods
On this page
Methods reference only. Use primary source citations and local policy before applying this in a study protocol, regulatory submission, payer dossier, or clinical decision.
In plain language

A biomarker-defined cohort is a study group built only from patients who had a specific molecular or lab test done AND received a qualifying result (for example, a genetic mutation found in their tumor). Because the test happens in routine care rather than a controlled trial, only patients who were actually tested can enter the study, and that tested group is not a random slice of all patients with the disease. The key trap to avoid is counting time before a patient got their test result as if they were already in the study, which makes survival look falsely better than it really is.

When to use it
When the clinical or HTA decision is itself biomarker-conditional (companion diagnostic, actionability tier).
Whenever the result is available; reserve test-order surrogates for testing-rate and utilization questions.
When the question is outcomes from biomarker ascertainment forward rather than from diagnosis.
Watch out for
Restricted to the tested subpopulation; generalizability to the full indication requires an explicit testing-selection argument.
Requires EHR/registry/linked data carrying the actual call; not feasible in claims-only data.
Cannot recover the full from-diagnosis estimand and conditions on surviving to test.

A biomarker-defined cohort restricts the study population to patients carrying (or lacking) a specific biomarker — an oncogenic driver mutation (e.g., EGFR, KRAS G12C, BRAF V600E), a protein-expression level (PD-L1 TPS ≥50%, HER2 IHC 3+), a genomic signature (tumor mutational burden, MSI-high/dMMR), or a laboratory threshold (eGFR, LDL-C, viral load). In real-world data the biomarker is not assigned at enrollment as in a trial; it is discovered through a test that was ordered in routine care at some point in the patient's trajectory. The central methodological problem is therefore not "who has the biomarker" but "how does conditioning on a test result — and the timing of that test — distort the cohort, the time axis, and the estimand." Getting the index date and the entry condition right is the entire game.

Core conceptual distinction

A biomarker-defined cohort sits at the intersection of three separable choices, and conflating them is the most common source of bias.

  1. Eligibility on biomarker status requires that the result actually exist in the data — so the analyzable population is the tested subset, not the underlying disease population, and tested patients differ systematically from untested ones (access, performance status, larger or progressing tumors that warrant profiling, academic-center care).
  2. Index date / time zero must be chosen so that biomarker status is known at entry and no follow-up is "guaranteed survived." Anchoring follow-up to the date of diagnosis while requiring a later NGS result builds in immortal time: a patient cannot appear in a biomarker-defined cohort unless they survived long enough to be tested and reported.
  3. Estimand: a descriptive prevalence/outcome in the biomarker-positive subgroup is a very different quantity from a comparative (biomarker-stratified treatment effect), and the latter inherits all the confounding-by-indication problems of any observational comparison plus the testing-selection layer on top.

Pros, cons, and trade-offs

  • vs an unselected (all-comers) disease cohort: A biomarker-defined cohort answers the precision-medicine question directly — efficacy, safety, utilization, or cost within the marker stratum — and supports external-control arms for marker-targeted therapies. Cost: it is restricted to the tested subpopulation, so generalizability to the full indication requires an explicit argument about who gets tested. Prefer it when the clinical and reimbursement decision is itself marker-conditional (companion diagnostic, ESCAT/OncoKB-tiered actionability).
  • vs defining the cohort on the biomarker test order (a CPT/HCPCS or order flag) rather than the result: Using the test event alone (common when only claims are available) tells you a test happened, never the result; it cannot separate positives from negatives and silently mixes strata. Prefer result-based definition whenever EHR/registry/NGS-report data carry the actual call; fall back to test-order proxies only for utilization/testing-rate questions, never for marker-conditional outcomes.

When NOT to use — and when it is actively misleading

  • Claims-only data with no result. Administrative claims carry CPT/HCPCS codes for the test (e.g., 81235 for EGFR, 81445/81455 for NGS panels, 0037U/0048U PLA codes, G-codes) but not the call. Defining "biomarker-positive" from claims alone is impossible; attempting it forces a test-order surrogate that misclassifies massively. Use linked or EHR data, or restrict the question to testing rates.
  • Immortal time from result-date anchoring. If you require a biomarker result obtained after the treatment line you are studying, every patient in the cohort survived from line start to test report — the line looks falsely protective. Nakamura et al. (2023) showed exactly this in a 5,743-patient genomic-profiling program: patients enrolled after first-line initiation had a median OS advantage of ~8.9 months purely from immortal time. Anchor entry at the result date with left truncation, or use a landmark/clone-censor-weight design.
  • Ignoring testing-selection. Tested patients are not a random sample of the diseased. A "biomarker-positive vs negative" contrast that does not address why some patients were tested (and others were not) confounds marker status with the indication-to-test. Report the tested-vs-untested comparison and, where possible, model selection or restrict to a setting with near-universal testing (e.g., reflex testing).
  • Assay/platform and threshold heterogeneity treated as one variable. PD-L1 by 22C3 vs SP263, HER2 IHC vs ISH, NGS variant-allele-frequency cutoffs, and OncoKB/ESCAT actionability tiers drift across labs and calendar time; variant reclassification (VUS → pathogenic) changes membership retroactively. Pooling them without a harmonization rule and a sensitivity analysis on the cut point produces a marker definition no one can reproduce.

Data-source operational depth

  • Claims (FFS or commercial): Useful only for the fact and date of testing (procedure/PLA codes) and for downstream utilization/cost once the cohort is defined elsewhere. Require continuous medical enrollment so an absent test code means "not tested," not "unobserved" — and note that Medicare Advantage and capitated/bundled arrangements drop fee-for-service claims, so MA-only person-time cannot confirm a test did or did not occur; restrict to enrollees with observable claims. Never read marker status from claims.
  • EHR: The biomarker result lives in pathology/molecular-report fields or unstructured notes; structured genomics tables exist only in mature systems and frequently require NLP/abstraction. Strengths: the actual call, assay, specimen date, and report date, plus indication and severity. Failure modes: results captured only when the test is in-network (external reference-lab reports leak out of the EHR), report-date vs specimen-date ambiguity, and visit-driven loss to follow-up that is differential by marker (positives funnel to targeted therapy and academic centers).
  • Registry (e.g., SEER, disease/genomic registries): Strong for adjudicated stage, histology, and often a curated biomarker field with defined assay rules; typically weak for complete treatment and pharmacy exposure. Link to claims for therapy and to a death index to firm up censoring and OS.
  • Linked EHR–claims–genomic (e.g., clinicogenomic databases): The ideal substrate — the genomic report supplies the result, the EHR supplies severity and treatment, claims supply completeness and cost, and a vital-records link supplies mortality. Singal et al. (2019) established this design for NSCLC. Costs: linkage selects the linkable subset, the NGS-tested cohort is itself selected, and report/specimen/treatment dates must be reconciled before time-zero assignment.

Worked example (linked EHR–claims–NGS, oncology)

Question: real-world overall survival of first-line osimertinib in EGFR-mutant advanced NSCLC.

  1. Source: a linked clinicogenomic database with NGS reports, EHR treatment records, and a death index.
  2. Biomarker definition: a structured EGFR exon-19 deletion or L858R call from an NGS or validated single-gene assay; record `assay_type`, `specimen_date`, and `report_date`; pre-specify how to treat VUS and which platforms qualify.
  3. Cohort entry to defeat immortal time: a patient becomes eligible only at `max(advanced_dx_date, egfr_result_date)`, and time zero is the first qualifying line start on or after that date — so biomarker status is known at entry and no pre-result, survived-to-test period is counted as exposed follow-up. If the estimand is OS from advanced diagnosis, instead left-truncate each patient's follow-up at `egfr_result_date` (delayed entry) so the risk set excludes time before testing.
  4. Tested-selection check: compare the EGFR-tested population to the broader advanced-NSCLC EHR population on stage, performance status, and site to characterize generalizability.
  5. Follow-up: from time zero to death, censoring at last EHR activity (treat as potentially informative) and end of data; reconcile `report_date` vs `specimen_date` and EHR vs claims service dates.
  6. Sensitivity analyses: alternative index-date rules (result-date entry vs left-truncation vs clone-censor-weight from diagnosis), VAF/threshold and assay-platform variations, and a negative-control marker to probe residual testing-selection.

Decision diagram

flowchart TD
  Pop[Advanced-disease patients in routine care] --> Tested{Biomarker test ordered<br/>and result captured?}
  Tested -- No --> Untested[Untested subset<br/>differs by access / severity / site]
  Tested -- Yes --> Result{Qualifying positive call?<br/>result-based, not test-order}
  Result -- No --> Neg[Biomarker-negative stratum]
  Result -- Yes --> Ascertain[Ascertainment date = report_date<br/>status now known in data]
  Ascertain --> Entry[Entry / time zero on or after ascertainment<br/>or left-truncate from diagnosis]
  Entry --> Sel[Report tested-vs-untested selection<br/>+ assay/threshold sensitivity]
  Sel --> Analysis[Marker-conditional outcome analysis]
Decision logic for a biomarker-defined cohort. Conditioning on a captured result selects the tested subset and requires entry at ascertainment (or left truncation) so that biomarker status is known at time zero and no survived-to-test person-time is counted.
gantt
  title Index-date choice for one biomarker-positive patient (immortal time)
  dateFormat YYYY-MM-DD
  axisFormat %b %Y
  section Pre-result (survived-to-test)
  Advanced diagnosis :milestone, dx, 2023-02-01, 0d
  First-line therapy started (status unknown) :crit, fl, 2023-02-10, 60d
  section Ascertainment
  NGS report -> EGFR positive :milestone, rep, 2023-04-15, 0d
  section Immortal-time-safe follow-up
  Risk set entry at result date (left truncation) :active, ft, 2023-04-15, 200d
Anchoring follow-up at diagnosis while requiring a later NGS result builds in immortal time (the red pre-result span); entering the risk set at the result date via left truncation removes the survived-to-test interval.

Worked example

Scenario

A researcher wants to study survival in patients with advanced lung cancer whose tumors carry an EGFR mutation. The electronic health record contains NGS (genomic panel) test reports. The table below shows five patients: their cancer diagnosis date, the date their EGFR mutation result came back, and whether they were tested at all. The goal is to decide who enters the cohort, when their follow-up clock starts, and what happens to patients who were never tested.

Dataset

Patient records: diagnosis date, EGFR test result date, and result. Untested patients have no result.

person_idadvanced_dx_dateegfr_result_dateegfr_resultqualifies
PT-012023-01-102023-02-05EGFR exon19del (positive)YES
PT-022023-01-152023-02-20EGFR wild-type (negative)NO
PT-032023-02-01never testedno resultNO
PT-042023-02-102023-03-01EGFR L858R (positive)YES
PT-052023-03-05died before resultno resultNO

Steps

1Step 1 - Who qualifies by biomarker result: Only PT-01 and PT-04 have a confirmed qualifying EGFR mutation in their test report. PT-02 tested negative, PT-03 was never tested, and PT-05 died before a result was available.
2Step 2 - Set each qualifying patient's index date to the later of their diagnosis date or their test result date. For PT-01: result date (2023-02-05) is after diagnosis (2023-01-10), so index date = 2023-02-05. For PT-04: result date (2023-03-01) is after diagnosis (2023-02-10), so index date = 2023-03-01.
3Step 3 - Do NOT count the time between diagnosis and the result date as study follow-up. PT-01 had 26 days between diagnosis and result; those 26 days are excluded. If we mistakenly started follow-up at diagnosis, every patient in the cohort would be a survivor of that pre-test window, making survival look better than it is (immortal time bias).
4Step 4 - Note the selection issue: 3 of 5 patients (60%) are excluded because they were untested or negative. The 2 who qualify may differ from the other 3 in ways that affect outcomes (they may have been tested because their disease was progressing rapidly, or because they had access to a comprehensive cancer center).

Result

Cohort size = 2 patients (PT-01, PT-04). Index dates: PT-01 on 2023-02-05, PT-04 on 2023-03-01. The 26-day and 19-day pre-result windows are excluded from follow-up. The 3 excluded patients represent the testing-selection issue: findings from this cohort describe EGFR-positive, tested patients only, not all advanced lung cancer patients.

Trade-offs

vs. Unselected (all comers) disease cohort
Pros of this
Answers the marker-conditional clinical, regulatory, and reimbursement question directly and supports biomarker-targeted external-control arms.
vs. Cohort defined on the biomarker test order rather than the result
Pros of this
Separates positives from negatives and enables true marker-conditional outcomes rather than a mixed-strata contrast.
vs. Target trial emulation with clone censor weight from diagnosis
Pros of this
Simpler to specify and communicate; left-truncated entry removes immortal time cleanly for outcomes measured from the result date forward.

Runnable example

Biomarker-defined cohort construction from linked EHR/genomic inputs, with index-date logic that defeats immortal time. Required inputs (already cleaned and de-duplicated): dx : advanced-disease diagnosis -> person_id, advanced_dx_date (datetime) bmarker : biomarker results -> person_id, report_date, specimen_date,...

requires: pandas
import pandas as pd

QUALIFYING = {("EGFR", "exon19del"), ("EGFR", "L858R")}  # pre-specified positive calls
ELIGIBLE_ASSAYS = {"NGS", "single_gene_validated"}        # pre-specified platforms

def build_biomarker_cohort(dx: pd.DataFrame, bmarker: pd.DataFrame, tx: pd.DataFrame) -> pd.DataFrame:
    # 1) Result-based positive definition; ascertainment date = report_date (when status becomes known).
    pos = bmarker[bmarker["assay_type"].isin(ELIGIBLE_ASSAYS)].copy()
    pos = pos[pos[["gene", "alteration"]].apply(tuple, axis=1).isin(QUALIFYING)]
    # Earliest qualifying report per person = the date biomarker status is first known in the data.
    ascertain = (pos.sort_values("report_date")
                    .groupby("person_id", as_index=False)
                    .agg(egfr_result_date=("report_date", "first"),
                         assay_type=("assay_type", "first")))

    cohort = dx.merge(ascertain, on="person_id", how="inner")  # tested + positive only

    # 2) Eligibility starts when BOTH advanced disease and a known positive result exist.
    cohort["eligible_from"] = cohort[["advanced_dx_date", "egfr_result_date"]].max(axis=1)

    # 3) Time zero = first treatment line starting ON OR AFTER eligibility (status known at entry,
    #    so no survived-to-test, pre-result person-time is counted as exposed follow-up).
    tx_sorted = tx.sort_values("line_start_date")
    merged = tx_sorted.merge(cohort[["person_id", "eligible_from"]], on="person_id")
    first_line = (merged[merged["line_start_date"] >= merged["eligible_from"]]
                  .groupby("person_id", as_index=False)
                  .first()
                  .rename(columns={"line_start_date": "index_date"}))

    out = cohort.merge(first_line[["person_id", "index_date", "regimen"]], on="person_id", how="inner")
    # 4) Alternative from-diagnosis estimand: left-truncate the risk set at the result date.
    out["truncation_entry"] = out["egfr_result_date"]  # delayed entry for OS-from-diagnosis analyses
    out["baseline_start"] = out["index_date"] - pd.Timedelta(days=365)  # covariate window ends at index
    return out[["person_id", "advanced_dx_date", "egfr_result_date", "assay_type",
                "index_date", "regimen", "truncation_entry", "baseline_start"]]

Citations

FOUNDATIONAL / METHODS
  1. [1]Singal G, Miller PG, Agarwala V, et al. Association of patient characteristics and tumor genomics with clinical outcomes among patients with non-small cell lung cancer using a clinicogenomic database. JAMA. 2019;321(14):1391-1399.
  2. [2]Suissa S, Dell'Aniello S. Time-related biases in pharmacoepidemiology. Pharmacoepidemiology and Drug Safety. 2020;29(9):1101-1110.
  3. [3]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. Journal of Clinical Epidemiology. 2016;79:70-75.
APPLIED EXAMPLES
  1. [4]Nakamura Y, Yamashita R, Okamoto W, et al. Efficacy of targeted trials and signaling pathway landscape in advanced gastrointestinal cancers from SCRUM-Japan GI-SCREEN: a nationwide genomic profiling program. JCO Precision Oncology. 2023;7:e2200653.
REPORTING & GUIDANCE
  1. [5]U.S. Food and Drug Administration. Enrichment Strategies for Clinical Trials to Support Determination of Effectiveness of Human Drugs and Biological Products: Guidance for Industry. 2019.