rxref is an R package for working with medication identifiers from the National Library of Medicine’s RxNorm and RxClass APIs. It provides tidy, vectorized helpers for resolving medication names to RxCUIs, expanding ingredients to product concepts, mapping between RxCUIs and NDCs, retrieving clinical product attributes, and querying selected drug class relationships.
The package is designed for pharmacoepidemiologic and health services research workflows where medication exposure definitions often need to move between ingredient names, RxNorm concepts, National Drug Codes (NDCs), routes, dose forms, and therapeutic classes.
rxref was originally built to support pharmacoepidemiologic research in the UF CVmedLab, where we often need reproducible, transparent medication definitions for prescriptions, pharmacy dispensings, and claims-based drug exposure measures.
Common workflows include:
find_ingredients() and resolve();products_for_ingredients();concept_status;map_to(),
map_rxcui_to_ndc(), and
map_ndc_to_rxcui();get_properties() and
get_clinical_attributes();filter_products_by_route();get_atc(), get_epc(), and
get_medrt();product_ttys() and tty_catalogue().You can install the development version of rxref from GitHub with:
# install.packages("pak")
# pak::pak("ssmithm/rxref")This is a basic example for querying product RxCUIs associated with the ingredient lisinopril (a blood pressure-lowering drug):
library(rxref)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
lisinopril_ing <- find_ingredients("lisinopril")
lisinopril_products <- products_for_ingredients(
lisinopril_ing$rxcui,
ttys = product_ttys("default"),
include_combos = TRUE
)
# Resulting table
lisinopril_products |>
dplyr::mutate(name = paste0("`", name, "`")) |>
knitr::kable()| ingredient_rxcui | product_rxcui | name | tty | n_ingredients |
|---|---|---|---|---|
| 29046 | 104375 | lisinopril 2.5 MG Oral Tablet [Zestril] |
SBD | 1 |
| 29046 | 104376 | lisinopril 5 MG Oral Tablet [Zestril] |
SBD | 1 |
| 29046 | 104377 | lisinopril 10 MG Oral Tablet [Zestril] |
SBD | 1 |
| 29046 | 104378 | lisinopril 20 MG Oral Tablet [Zestril] |
SBD | 1 |
| 29046 | 1806890 | lisinopril 1 MG/ML Oral Solution [Qbrelis] |
SBD | 1 |
| 29046 | 206765 | lisinopril 10 MG Oral Tablet [Prinivil] |
SBD | 1 |
| 29046 | 206766 | lisinopril 20 MG Oral Tablet [Prinivil] |
SBD | 1 |
| 29046 | 206771 | lisinopril 40 MG Oral Tablet [Zestril] |
SBD | 1 |
| 29046 | 213482 | lisinopril 30 MG Oral Tablet [Zestril] |
SBD | 1 |
| 29046 | 823971 | hydrochlorothiazide 25 MG / lisinopril 20 MG Oral Tablet [Zestoretic] |
SBD | 2 |
| 29046 | 823982 | hydrochlorothiazide 12.5 MG / lisinopril 20 MG Oral Tablet [Zestoretic] |
SBD | 2 |
| 29046 | 823986 | hydrochlorothiazide 12.5 MG / lisinopril 10 MG Oral Tablet [Zestoretic] |
SBD | 2 |
| 29046 | 1806884 | lisinopril 1 MG/ML Oral Solution |
SCD | 1 |
| 29046 | 197884 | lisinopril 40 MG Oral Tablet |
SCD | 1 |
| 29046 | 197885 | hydrochlorothiazide 12.5 MG / lisinopril 10 MG Oral Tablet |
SCD | 2 |
| 29046 | 197886 | hydrochlorothiazide 12.5 MG / lisinopril 20 MG Oral Tablet |
SCD | 2 |
| 29046 | 197887 | hydrochlorothiazide 25 MG / lisinopril 20 MG Oral Tablet |
SCD | 2 |
| 29046 | 205326 | lisinopril 30 MG Oral Tablet |
SCD | 1 |
| 29046 | 311353 | lisinopril 2.5 MG Oral Tablet |
SCD | 1 |
| 29046 | 311354 | lisinopril 5 MG Oral Tablet |
SCD | 1 |
| 29046 | 314076 | lisinopril 10 MG Oral Tablet |
SCD | 1 |
| 29046 | 314077 | lisinopril 20 MG Oral Tablet |
SCD | 1 |
# Count of TTYs in resulting table
lisinopril_products |>
count(tty, n_ingredients, sort=TRUE)
#> # A tibble: 4 × 3
#> tty n_ingredients n
#> <chr> <int> <int>
#> 1 SBD 1 9
#> 2 SCD 1 7
#> 3 SBD 2 3
#> 4 SCD 2 3By default, products_for_ingredients() searches active
RxNorm concepts:
products_for_ingredients(
"29046",
ttys = product_ttys("extended_product"),
concept_status = "active"
) |> knitr::kable()| ingredient_rxcui | product_rxcui | name | tty | n_ingredients |
|---|---|---|---|---|
| 29046 | 1806883 | lisinopril Oral Solution | SCDF | 1 |
| 29046 | 372613 | hydrochlorothiazide / lisinopril Oral Tablet | SCDF | 2 |
| 29046 | 372614 | lisinopril Oral Tablet | SCDF | 1 |
| 29046 | 1162124 | hydrochlorothiazide / lisinopril Oral Product | SCDG | 2 |
| 29046 | 1162125 | hydrochlorothiazide / lisinopril Pill | SCDG | 2 |
| 29046 | 1164689 | lisinopril Oral Product | SCDG | 1 |
| 29046 | 1164690 | lisinopril Pill | SCDG | 1 |
| 29046 | 1806882 | lisinopril Oral Liquid Product | SCDG | 1 |
| 29046 | 104375 | lisinopril 2.5 MG Oral Tablet [Zestril] | SBD | 1 |
| 29046 | 104376 | lisinopril 5 MG Oral Tablet [Zestril] | SBD | 1 |
| 29046 | 104377 | lisinopril 10 MG Oral Tablet [Zestril] | SBD | 1 |
| 29046 | 104378 | lisinopril 20 MG Oral Tablet [Zestril] | SBD | 1 |
| 29046 | 1806890 | lisinopril 1 MG/ML Oral Solution [Qbrelis] | SBD | 1 |
| 29046 | 206765 | lisinopril 10 MG Oral Tablet [Prinivil] | SBD | 1 |
| 29046 | 206766 | lisinopril 20 MG Oral Tablet [Prinivil] | SBD | 1 |
| 29046 | 206771 | lisinopril 40 MG Oral Tablet [Zestril] | SBD | 1 |
| 29046 | 213482 | lisinopril 30 MG Oral Tablet [Zestril] | SBD | 1 |
| 29046 | 823971 | hydrochlorothiazide 25 MG / lisinopril 20 MG Oral Tablet [Zestoretic] | SBD | 2 |
| 29046 | 823982 | hydrochlorothiazide 12.5 MG / lisinopril 20 MG Oral Tablet [Zestoretic] | SBD | 2 |
| 29046 | 823986 | hydrochlorothiazide 12.5 MG / lisinopril 10 MG Oral Tablet [Zestoretic] | SBD | 2 |
| 29046 | 1806887 | lisinopril Oral Solution [Qbrelis] | SBDF | 1 |
| 29046 | 368248 | lisinopril Oral Tablet [Zestril] | SBDF | 1 |
| 29046 | 368865 | lisinopril Oral Tablet [Prinivil] | SBDF | 1 |
| 29046 | 823970 | hydrochlorothiazide / lisinopril Oral Tablet [Zestoretic] | SBDF | 2 |
| 29046 | 1178275 | Prinivil Oral Product | SBDG | 1 |
| 29046 | 1178276 | Prinivil Pill | SBDG | 1 |
| 29046 | 1187277 | Zestoretic Oral Product | SBDG | 2 |
| 29046 | 1187278 | Zestoretic Pill | SBDG | 2 |
| 29046 | 1187283 | Zestril Oral Product | SBDG | 1 |
| 29046 | 1187284 | Zestril Pill | SBDG | 1 |
| 29046 | 1806888 | Qbrelis Oral Liquid Product | SBDG | 1 |
| 29046 | 1806889 | Qbrelis Oral Product | SBDG | 1 |
| 29046 | 1806884 | lisinopril 1 MG/ML Oral Solution | SCD | 1 |
| 29046 | 197884 | lisinopril 40 MG Oral Tablet | SCD | 1 |
| 29046 | 197885 | hydrochlorothiazide 12.5 MG / lisinopril 10 MG Oral Tablet | SCD | 2 |
| 29046 | 197886 | hydrochlorothiazide 12.5 MG / lisinopril 20 MG Oral Tablet | SCD | 2 |
| 29046 | 197887 | hydrochlorothiazide 25 MG / lisinopril 20 MG Oral Tablet | SCD | 2 |
| 29046 | 205326 | lisinopril 30 MG Oral Tablet | SCD | 1 |
| 29046 | 311353 | lisinopril 2.5 MG Oral Tablet | SCD | 1 |
| 29046 | 311354 | lisinopril 5 MG Oral Tablet | SCD | 1 |
| 29046 | 314076 | lisinopril 10 MG Oral Tablet | SCD | 1 |
| 29046 | 314077 | lisinopril 20 MG Oral Tablet | SCD | 1 |
For older prescribing (or dispensing) data, users may need products
that are no longer active in the current RxNorm release. Set
concept_status = "active_and_historical" to include active
concepts plus selected historical statuses:
products_for_ingredients(
"1369",
ttys = "SCD",
include_combos = FALSE,
concept_status = "active_and_historical"
) |> knitr::kable()| ingredient_rxcui | product_rxcui | name | tty | n_ingredients | concept_status | active_start_date | active_end_date | release_start_date | release_end_date |
|---|---|---|---|---|---|---|---|---|---|
| 1369 | 197394 | bendroflumethiazide 5 MG Oral Tablet | SCD | 1 | Active | NA | NA | NA | NA |
| 1369 | 308614 | bendroflumethiazide 2.5 MG Oral Tablet | SCD | 1 | Active | NA | NA | NA | NA |
| 1369 | 197393 | bendroflumethiazide 10 MG Oral Tablet | SCD | 1 | Obsolete | 042005 | 062014 | 042005 | |
| 1369 | 308617 | bendroflumethiazide 5 MG Extended Release Oral Tablet | SCD | 1 | Obsolete | 042005 | 092010 | 042005 | |
| 1369 | 429502 | bendroflumethiazide 1.25 MG Oral Tablet | SCD | 1 | Obsolete | 042005 | 072005 | 042005 |
Historical searches return additional status and date fields, including concept_status, active_start_date, active_end_date, release_start_date, and release_end_date.
Note: Historical searches are slower than
active-only searches because they require broader RxNorm status lookups.
rxref caches repeated API calls where possible, but
active-only queries should be preferred when historical concepts are not
needed.
get_clinical_attributes() retrieves product-level
attributes such as ingredients, dose form, dose form group, route,
strength, and ingredient count.
attrs <- get_clinical_attributes(lisinopril_products$product_rxcui)
attrs |>
select(rxcui, related_rxcui, name, strength, dose_form, route, tty)
#> # A tibble: 22 × 7
#> rxcui related_rxcui name strength dose_form route tty
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 104375 104375 lisinopril 2.5 MG Oral … 2.5 MG Oral Tab… ORAL SBD
#> 2 104376 104376 lisinopril 5 MG Oral Ta… 5 MG Oral Tab… ORAL SBD
#> 3 104377 104377 lisinopril 10 MG Oral T… 10 MG Oral Tab… ORAL SBD
#> 4 104378 104378 lisinopril 20 MG Oral T… 20 MG Oral Tab… ORAL SBD
#> 5 1806890 1806890 lisinopril 1 MG/ML Oral… 1 MG/ML Oral Sol… ORAL SBD
#> 6 206765 206765 lisinopril 10 MG Oral T… 10 MG Oral Tab… ORAL SBD
#> 7 206766 206766 lisinopril 20 MG Oral T… 20 MG Oral Tab… ORAL SBD
#> 8 206771 206771 lisinopril 40 MG Oral T… 40 MG Oral Tab… ORAL SBD
#> 9 213482 213482 lisinopril 30 MG Oral T… 30 MG Oral Tab… ORAL SBD
#> 10 823971 823971 hydrochlorothiazide 25 … 25 MG /… Oral Tab… ORAL SBD
#> # ℹ 12 more rowsProducts can also be filtered by route:
oral_lisinopril <- filter_products_by_route(
lisinopril_products,
route = "ORAL"
)
oral_lisinopril
#> # A tibble: 22 × 8
#> ingredient_rxcui product_rxcui name tty n_ingredients route dose_form
#> <chr> <chr> <chr> <chr> <int> <chr> <chr>
#> 1 29046 104375 lisinopri… SBD 1 ORAL Oral Tab…
#> 2 29046 104376 lisinopri… SBD 1 ORAL Oral Tab…
#> 3 29046 104377 lisinopri… SBD 1 ORAL Oral Tab…
#> 4 29046 104378 lisinopri… SBD 1 ORAL Oral Tab…
#> 5 29046 1806890 lisinopri… SBD 1 ORAL Oral Sol…
#> 6 29046 206765 lisinopri… SBD 1 ORAL Oral Tab…
#> 7 29046 206766 lisinopri… SBD 1 ORAL Oral Tab…
#> 8 29046 206771 lisinopri… SBD 1 ORAL Oral Tab…
#> 9 29046 213482 lisinopri… SBD 1 ORAL Oral Tab…
#> 10 29046 823971 hydrochlo… SBD 2 ORAL Oral Tab…
#> # ℹ 12 more rows
#> # ℹ 1 more variable: dose_form_group <chr>RxCUIs can be mapped to NDCs (and vice-versa):
ndcs <- map_rxcui_to_ndc("314077")
ndcs
#> # A tibble: 249 × 3
#> rxcui ndc11 ndc_status
#> <chr> <chr> <chr>
#> 1 314077 00143971301 ACTIVE
#> 2 314077 00143971310 ACTIVE
#> 3 314077 00185062001 ACTIVE
#> 4 314077 00185062010 ACTIVE
#> 5 314077 00378207501 ACTIVE
#> 6 314077 00378207510 ACTIVE
#> 7 314077 00591040801 ACTIVE
#> 8 314077 00591040810 ACTIVE
#> 9 314077 00615825505 ACTIVE
#> 10 314077 00615825530 ACTIVE
#> # ℹ 239 more rowsThe direction-agnostic map_to() function can be used
when you want to map between identifier types with one interface:
map_to("314077", to = "ndc")
#> # A tibble: 249 × 3
#> rxcui ndc11 ndc_status
#> <chr> <chr> <chr>
#> 1 314077 00143971301 ACTIVE
#> 2 314077 00143971310 ACTIVE
#> 3 314077 00185062001 ACTIVE
#> 4 314077 00185062010 ACTIVE
#> 5 314077 00378207501 ACTIVE
#> 6 314077 00378207510 ACTIVE
#> 7 314077 00591040801 ACTIVE
#> 8 314077 00591040810 ACTIVE
#> 9 314077 00615825505 ACTIVE
#> 10 314077 00615825530 ACTIVE
#> # ℹ 239 more rowsrxref includes selected helpers for querying RxClass
relationships, including ATC, EPC, and MED-RT classes.
get_atc("29046")
#> # A tibble: 1 × 10
#> input rxcui drug_name drug_tty class_id class_name class_type class_url rela
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 29046 29046 lisinopril IN C09AA ACE inhib… ATC1-4 <NA> ""
#> # ℹ 1 more variable: rela_source <chr>
get_epc("29046")
#> # A tibble: 2 × 10
#> input rxcui drug_name drug_tty class_id class_name class_type class_url rela
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 29046 15460… lisinopr… PIN N000017… Angiotens… EPC <NA> has_…
#> 2 29046 15460… lisinopr… PIN N000017… Angiotens… EPC <NA> has_…
#> # ℹ 1 more variable: rela_source <chr>
get_medrt("29046")
#> # A tibble: 43 × 10
#> input rxcui drug_name drug_tty class_id class_name class_type class_url rela
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 29046 1546… lisinopr… PIN D000799 Angioedema DISEASE <NA> ci_w…
#> 2 29046 1546… lisinopr… PIN D003928 Diabetic … DISEASE <NA> may_…
#> 3 29046 1546… lisinopr… PIN D003928 Diabetic … DISEASE <NA> may_…
#> 4 29046 1546… lisinopr… PIN D004342 Drug Hype… DISEASE <NA> ci_w…
#> 5 29046 1546… lisinopr… PIN D006333 Heart Fai… DISEASE <NA> may_…
#> 6 29046 1546… lisinopr… PIN D006929 Hyperaldo… DISEASE <NA> ci_w…
#> 7 29046 1546… lisinopr… PIN D006973 Hypertens… DISEASE <NA> may_…
#> 8 29046 1546… lisinopr… PIN D007022 Hypotensi… DISEASE <NA> ci_w…
#> 9 29046 1546… lisinopr… PIN D009203 Myocardia… DISEASE <NA> may_…
#> 10 29046 1546… lisinopr… PIN D011247 Pregnancy DISEASE <NA> ci_w…
#> # ℹ 33 more rows
#> # ℹ 1 more variable: rela_source <chr>rxref queries public RxNorm and RxClass APIs. The
package includes configurable rate-delay and caching behavior to reduce
repeated API requests and to support longer medication-definition
workflows. Note that RxNorm indicates a rate of no more than
20 API requests per second per IP.
rxref_conf()
#> $base_url
#> [1] "https://rxnav.nlm.nih.gov/REST"
#>
#> $rate_delay
#> [1] 0.1
#>
#> $cache
#> <cache_mem> <cachem>
#> Methods:
#> get(key, missing = missing_)
#> set(key, value)
#> exists(key)
#> keys()
#> remove(key)
#> reset()
#> prune()
#> size()
#> info()
rxref_conf(rate_delay = 0.1)
#> $base_url
#> [1] "https://rxnav.nlm.nih.gov/REST"
#>
#> $rate_delay
#> [1] 0.1
#>
#> $cache
#> <cache_mem> <cachem>
#> Methods:
#> get(key, missing = missing_)
#> set(key, value)
#> exists(key)
#> keys()
#> remove(key)
#> reset()
#> prune()
#> size()
#> info()RxNorm concepts and NDC mappings can change over time. For reproducible research, consider recording the date of API access and retaining intermediate drug-definition outputs used in analyses.
rxref is intended to support research workflows and
medication-definition development. Users should review outputs carefully
before using them in any high-stakes regulatory, clinical, or production
settings.