
Composable phenotype cohort DSL compiled to single-pass DuckDB SQL
Source:R/phenotype_dsl.R
phenotype_criteria.RdBuild a cohort definition from clinical criteria and logical operators, then compile it to one DuckDB
query (or run it into a cohort table) - the R mirror of omop_etl.phenotype_dsl in Python:
Usage
condition_criteria(
concept_ids = NULL,
icd_codes = NULL,
icd_vocabularies = c("ICD9CM", "ICD10CM"),
diagnosis = c("any", "primary", "secondary"),
include_descendants = TRUE,
min_occurrences = 1L,
lookback_days = NULL,
lookahead_days = NULL
)
measurement_criteria(
concept_ids = NULL,
loinc_codes = NULL,
value_gte = NULL,
value_gt = NULL,
value_lte = NULL,
value_lt = NULL,
unit_concept_ids = NULL,
include_descendants = FALSE,
min_occurrences = 1L,
lookback_days = NULL,
lookahead_days = NULL
)
drug_criteria(
concept_ids = NULL,
atc_codes = NULL,
min_days_supply = NULL,
include_descendants = TRUE,
min_occurrences = 1L,
lookback_days = NULL,
lookahead_days = NULL
)Arguments
- concept_ids
Standard concept ids (descendants are included via
concept_ancestorwheninclude_descendants = TRUE).- icd_codes
ICD-9/10 code prefixes (
"E11"matchesE11.9), matched againstcondition_source_valueand the source concept's code.- icd_vocabularies
Vocabularies the source-concept match is restricted to.
- diagnosis
"any","primary"or"secondary"(viacondition_status_concept_id).- include_descendants
Expand
concept_idsthroughconcept_ancestor.- min_occurrences
Require at least this many qualifying records; the index date is the n-th one.
- lookback_days, lookahead_days
Window around the index table's date (requires
index_table).- loinc_codes
LOINC codes, matched on
measurement_source_valueand the concept's code.- value_gte, value_gt, value_lte, value_lt
Thresholds on
value_as_number(all must hold).- unit_concept_ids
Restrict measurements to these units.
- atc_codes
ATC codes resolved through
conceptas additional ancestor concepts.- min_days_supply
Require
days_supply(or end - start when unset) of at least this many days.
Details
t2dm <- condition_criteria(icd_codes = "E11", concept_ids = 201826) |
measurement_criteria(loinc_codes = "4548-4", value_gte = 6.5) |
drug_criteria(concept_ids = 21600712, min_days_supply = 30)
execute_phenotype(con, t2dm & !condition_criteria(icd_codes = "E10"), "cohort", cohort_definition_id = 7)Criteria (condition_criteria(), measurement_criteria(), drug_criteria(), everyone()) are leaves;
| / phenotype_union(), & / phenotype_intersect() and ! / phenotype_not() compose them.
Single pass. Every leaf emits (person_id, event_date, leaf) rows into one UNION ALL; one
GROUP BY person_id computes each leaf's qualifying date with FILTER clauses, and the boolean tree is
evaluated as one WHERE over those columns. No leaf is re-scanned per operator and no intermediate cohort
tables are created.
Index date. A person's index date is the earliest qualifying event for a union, and the latest of the
operands' qualifying dates for an intersection (the moment every criterion is first satisfied). ! only
excludes. With index_table = the index date is that table's date instead, and a leaf's lookback_days /
lookahead_days are measured relative to it: lookback only gives [index - n, index], lookahead only
[index, index + m], both [index - n, index + m].