peridefs provides code sets (ICD-9, ICD-10, and
HCPCS/CPT) to define conditions such as hypertension, diabetes, and
atherosclerotic cardiovascular disease in real world claims data. It
also contains generic names for common drug types (e.g., anti-diabetes).
The purpose of the peridefs package is to provide safe and
easy access to these validated definitions.
Retrieving condition codes
Each condition has one or more
get_<condition>_vX_codes() functions — one per
algorithm version. Every get_* function in
peridefs returns a tidy data frame:
get_hypertension_v1_codes()
#> # A tibble: 36 × 5
#> type code priority version definition
#> <chr> <chr> <int> <chr> <chr>
#> 1 dx_icd9 401 1 v1 Essential hypertension
#> 2 dx_icd9 4010 1 v1 Malignant essential hypertension
#> 3 dx_icd9 4011 1 v1 Benign essential hypertension
#> 4 dx_icd9 4019 1 v1 Unspecified essential hypertension
#> 5 dx_icd9 4030 1 v1 Hypertensive chronic kidney disease: Malignant
#> 6 dx_icd9 40300 1 v1 Hypertensive chronic kidney disease, malignan…
#> 7 dx_icd9 40301 1 v1 Hypertensive chronic kidney disease, malignan…
#> 8 dx_icd9 4031 1 v1 Hypertensive chronic kidney disease: Benign
#> 9 dx_icd9 40310 1 v1 Hypertensive chronic kidney disease, benign, …
#> 10 dx_icd9 40311 1 v1 Hypertensive chronic kidney disease, benign, …
#> # ℹ 26 more rowsThe priority column reflects our confidence that a code
belongs in the definition (1 = core, 2 =
probable, 3 = cautious); by default only
priority = 1 rows are returned. The version
column identifies which version of the spec produced each row.
Selecting a code type
By default, get_ functions will return all relevant
codes or generics. If you only want to return a specific type or types
of codes, use the code_type argument to retrieve a filtered
code list. Supprted values are "dx_icd9",
"dx_icd10", "hcpcs", "proc_icd9",
and "proc_icd10":
get_hypertension_v1_codes(code_type = "dx_icd10")
#> # A tibble: 23 × 5
#> type code priority version definition
#> <chr> <chr> <int> <chr> <chr>
#> 1 dx_icd10 I10 1 v1 Essential (primary) hypertension
#> 2 dx_icd10 I11 1 v1 Hypertensive heart disease
#> 3 dx_icd10 I110 1 v1 Hypertensive heart disease with heart failure
#> 4 dx_icd10 I119 1 v1 Hypertensive heart disease without heart fai…
#> 5 dx_icd10 I12 1 v1 Hypertensive chronic kidney disease
#> 6 dx_icd10 I120 1 v1 Hypertensive chronic kidney disease with sta…
#> 7 dx_icd10 I129 1 v1 Hypertensive chronic kidney disease with sta…
#> 8 dx_icd10 I13 1 v1 Hypertensive heart and chronic kidney disease
#> 9 dx_icd10 I130 1 v1 Hypertensive heart and chronic kidney diseas…
#> 10 dx_icd10 I131 1 v1 Hypertensive heart and chronic kidney diseas…
#> # ℹ 13 more rowsNote that if you ask for a code type that isn’t stored in the object, you get an empty tibble.
get_hypertension_v1_codes(code_type = 'proc_icd10')
#> # A tibble: 0 × 5
#> # ℹ 5 variables: type <chr>, code <chr>, priority <int>, version <chr>,
#> # definition <chr>Adding periods to codes
Codes are stored in short format (no periods, i.e., .)
as this is a common format in claims data. Set
periods = TRUE to add them to your codes:
get_hypertension_v1_codes(code_type = "dx_icd10", periods = TRUE)
#> # A tibble: 23 × 5
#> type code priority version definition
#> <chr> <chr> <int> <chr> <chr>
#> 1 dx_icd10 I10 1 v1 Essential (primary) hypertension
#> 2 dx_icd10 I11 1 v1 Hypertensive heart disease
#> 3 dx_icd10 I11.0 1 v1 Hypertensive heart disease with heart failure
#> 4 dx_icd10 I11.9 1 v1 Hypertensive heart disease without heart fai…
#> 5 dx_icd10 I12 1 v1 Hypertensive chronic kidney disease
#> 6 dx_icd10 I12.0 1 v1 Hypertensive chronic kidney disease with sta…
#> 7 dx_icd10 I12.9 1 v1 Hypertensive chronic kidney disease with sta…
#> 8 dx_icd10 I13 1 v1 Hypertensive heart and chronic kidney disease
#> 9 dx_icd10 I13.0 1 v1 Hypertensive heart and chronic kidney diseas…
#> 10 dx_icd10 I13.1 1 v1 Hypertensive heart and chronic kidney diseas…
#> # ℹ 13 more rowsNote that this feature is not perfect - it just adds a period after the third character. Periods appear after the third character in ICD-10 but may appear after the fourth in ICD-9. Most of our analyses focus on ICD-10 and most databases do not use periods in codes, so getting this exactly right is not a high priority at the moment.
Condition vs. outcome definitions
Some specs carry separate code sets for identifying a
condition (history / comorbidity lookback) vs. an
outcome (new event). Use variable_type to
select one:
get_hf_v1_codes(variable_type = "outcome", code_type = "dx_icd10")
#> # A tibble: 26 × 5
#> type code priority version definition
#> <chr> <chr> <int> <chr> <chr>
#> 1 dx_icd10 I110 1 v1 Hypertensive heart disease with heart failure
#> 2 dx_icd10 I130 1 v1 Hypertensive heart and chronic kidney diseas…
#> 3 dx_icd10 I132 1 v1 Hypertensive heart and chronic kidney diseas…
#> 4 dx_icd10 I501 1 v1 Left ventricular failure, unspecified
#> 5 dx_icd10 I5020 1 v1 Unspecified systolic (congestive) heart fail…
#> 6 dx_icd10 I5021 1 v1 Acute systolic (congestive) heart failure
#> 7 dx_icd10 I5022 1 v1 Chronic systolic (congestive) heart failure
#> 8 dx_icd10 I5023 1 v1 Acute on chronic systolic (congestive) heart…
#> 9 dx_icd10 I5030 1 v1 Unspecified diastolic (congestive) heart fai…
#> 10 dx_icd10 I5031 1 v1 Acute diastolic (congestive) heart failure
#> # ℹ 16 more rowsThe default (variable_type = "condition") retrieves the
condition definition.
Composite specs and the component argument
Some specs are composites — they contain several
named component specs rather than a single code set.
spec_ascvd, for example, groups coronary heart disease
(CHD), stroke, lower extremity artery disease (LEAD) / peripheral
arterial disease (PAD), and cerebrovascular disease into a single
composition.
For composite specs, the component argument is optional.
Omitting it (or passing "all") returns every component at
once, distinguished by a class column. Print the spec to
see all available component names:
spec_ascvd
#>
#> ── Atherosclerotic Cardiovascular Disease (ASCVD) (composite) ──────────────────
#> Condition: `ascvd`
#> Def: Composition of all ASCVD component specs: coronary heart disease (CHD),
#> stroke, lower extremity artery disease (LEAD) / peripheral arterial disease
#> (PAD), and cerebrovascular disease
#> Components:
#> `chd_v1`: Coronary Heart Disease
#> `stroke_v1`: Stroke (Any)
#> `lead_pad_v1`: lower extremity artery disease (LEAD) / peripheral artery
#> disease (PAD)
#> `cerebrovasc_disease_v1`: Cerebrovascular Disease
#> Use `component` = "chd_v1", "stroke_v1", "lead_pad_v1", and
#> "cerebrovasc_disease_v1" in `get_*()` functions.
#> Default components by variable_type:
#> condition: "chd_v1", "cerebrovasc_disease_v1", and "lead_pad_v1"
#> outcome: "chd_v1", "stroke_v1", and "lead_pad_v1"Retrieve codes for a single component:
get_ascvd_codes(component = "chd_v1", code_type = "dx_icd10")
#> # A tibble: 46 × 6
#> type code priority version definition class
#> <chr> <chr> <int> <chr> <chr> <chr>
#> 1 dx_icd10 I21 1 v1 Acute myocardial infarction chd
#> 2 dx_icd10 I210 1 v1 ST elevation (STEMI) myocardial infarc… chd
#> 3 dx_icd10 I2101 1 v1 ST elevation (STEMI) myocardial infarc… chd
#> 4 dx_icd10 I2102 1 v1 ST elevation (STEMI) myocardial infarc… chd
#> 5 dx_icd10 I2109 1 v1 ST elevation (STEMI) myocardial infarc… chd
#> 6 dx_icd10 I211 1 v1 ST elevation (STEMI) myocardial infarc… chd
#> 7 dx_icd10 I2111 1 v1 ST elevation (STEMI) myocardial infarc… chd
#> 8 dx_icd10 I2119 1 v1 ST elevation (STEMI) myocardial infarc… chd
#> 9 dx_icd10 I212 1 v1 ST elevation (STEMI) myocardial infarc… chd
#> 10 dx_icd10 I2121 1 v1 ST elevation (STEMI) myocardial infarc… chd
#> # ℹ 36 more rowsOmit component (or pass "all") to get every
component’s codes at once:
get_ascvd_codes(code_type = "dx_icd10") |> nrow()
#> [1] 456Reading algorithm definitions
The codes are only half of what you need to get definitions right.
You also need to know how to apply them.
get_<condition>_vX_defs() provides a description of
the algorithm used to define each condition:
get_hypertension_v1_defs()
#> ℹ Any of the following:
#> • ≥1 inpatient claim with an ICD-9 discharge diagnosis of 401.x, 403.0x,
#> 403.1x, or 403.9x, or ICD-10 discharge diagnosis code of I10, I11.x, I12.x,
#> I13.x, I15.x, I12.0, I12.9, I16.x in any discharge diagnosis position.
#> • ≥2 outpatient physician visit claims with the same diagnosis codes, at least
#> 30 days apart.
#> • ≥2 pharmacy fills for an antihypertensive medication (see spec_hypertension)For composite specs, pass the component name:
get_ascvd_defs(component = "chd_v1", variable_type = "condition")
#> ℹ Any of the following:
#> • ≥1 inpatient claim with an ICD-9 diagnosis code of 410.xx–414.xx, V45.81, or
#> V45.82, or an ICD-10 diagnosis code of I21.xxx, I22.xxx, or specified
#> I25/I20/I24 codes in any position.
#> • ≥1 outpatient claim with the same ICD codes in any position.
#> • ≥1 inpatient or outpatient claim with an ICD-9 procedure code of 00.66, 36.0,
#> 36.01–36.19, or 36.2; an ICD-10-PCS code for CABG or PCI; or a HCPCS code for
#> coronary revascularization.Versioning
Algorithm versions are encoded directly in the spec and function
names using a _vX suffix (e.g., spec_acei_v1,
spec_acei_v2), used when a spec’s codes or generics
genuinely change between versions. Conditions like hypertension
previously had multiple versions that shared identical codes and
differed only in the narrative definition (e.g., whether a medication
criterion was included) — those have been collapsed into a single
version, so
spec_hypertension_v1/get_hypertension_v1_codes()/get_hypertension_v1_defs()
always reflect the most current definition.
Spec objects
Behind every get_* function is a spec_*
data object. You can inspect it directly to see codes, definitions, and
(for composites) component names:
spec_hypertension_v1
#>
#> ── Hypertension (v1) ───────────────────────────────────────────────────────────
#> Condition: `hypertension`
#> Condition def:
#> ℹ Any of the following:
#> • ≥1 inpatient claim with an ICD-9 discharge diagnosis of 401.x, 403.0x,
#> 403.1x, or 403.9x, or ICD-10 discharge diagnosis code of I10, I11.x, I12.x,
#> I13.x, I15.x, I12.0, I12.9, I16.x in any discharge diagnosis position.
#> • ≥2 outpatient physician visit claims with the same diagnosis codes, at least
#> 30 days apart.
#> • ≥2 pharmacy fills for an antihypertensive medication (see spec_hypertension)
#>
#> Code sets:
#> `dx_icd9`: 13 condition / 0 outcome codes
#> `dx_icd10`: 23 condition / 0 outcome codesComplement with icd package
The icd package is not required for
peridefs, but it can be used to complement it. In
particular, if you want to look up the explanations of our diagnostic
codes, icd is helpful and easy to apply:
library(icd) # for as.icd9 / as.icd10 / explain_code functions
library(tidyverse)
peri_codes <- get_copd_v1_codes(code_type = 'dx_icd9')$code
as.icd9(peri_codes) %>%
set_names(peri_codes) %>%
map_chr(~explain_code(.x)) %>%
enframe(name = 'code', value = 'explanation')
Note this only works for diagnostic codes and
explain_code sometimes fails to give explanations for all
codes if you pass a vector (that’s why I used map in my code).
Learn more
See the Reference for the complete list of conditions and drugs.