Overview
rxref provides tidy, vectorized helpers for working with
drug identifiers and metadata from the RxNorm and RxClass APIs. It is
designed for workflows that need to resolve drug names, RxCUIs, and
NDCs; retrieve RxNorm concept metadata; expand ingredients to product
concepts; map products to NDCs; and build medication lists for
pharmacoepidemiologic or health services research.
Common tasks include:
- resolving messy drug names or NDCs to RxCUIs;
- retrieving RxNorm concept properties;
- mapping NDCs to RxCUIs, or RxCUIs to NDCs;
- finding ingredients and related product concepts;
- creating route-specific product or NDC lists;
- optionally including historical RxNorm concepts when studying older calendar periods.
The examples below are not evaluated when the vignette is built, because they query live APIs. You can run them interactively after installing rxref.
Installation
Install the stable version of rxref from CRAN:
# Install from CRAN
# install.packages("rxref")Or the development version:
# install.packages("pak")
# pak::pak("ssmithm/rxref")Then load the package (the vignette will also use dplyr).
Resolve messy inputs to RxCUIs
The resolve() function accepts common drug identifiers,
including free-text drug names, NDCs, and RxCUIs. This is often the
first step when working with real-world medication data.
The returned object includes the original input, the resolved RxCUI, and available concept information.
Retrieve properties for RxCUIs
Once you have one or more RxCUIs, use get_properties()
to retrieve RxNorm concept metadata. This is useful when you want to
inspect concept names, term types, suppress status, or other basic
RxNorm properties.
ids <- c("860975", "860976")
get_properties(ids)Map NDCs and RxCUIs
rxref includes helpers for mapping between NDCs and
RxCUIs.
To map NDCs to RxCUIs:
map_ndc_to_rxcui(c(
"00093-1048-01",
"00093-1048-10"
))To map an RxCUI to NDCs:
map_rxcui_to_ndc("860975")You can optionally filter NDC mappings by NDC status:
map_rxcui_to_ndc("860975", status = "ACTIVE")NDC status and RxNorm concept status are related but distinct. NDC status refers to whether an NDC is active, obsolete, or otherwise categorized by RxNav. RxNorm concept status refers to whether the RxNorm concept itself is active or historical.
Find ingredients
The find_ingredients() function helps identify
ingredient-level RxCUIs from approximate drug names.
find_ingredients(c("metformin", "semaglutide", "lisinopril"))For many medication list workflows, users first identify a set of ingredient RxCUIs and then expand those ingredients to product concepts.
ingredients <- find_ingredients(c("metformin", "semaglutide")) |>
filter(tty == "IN") |>
distinct(
ingredient_rxcui = rxcui,
ingredient_name = name
)
ingredientsExpand ingredients to product concepts
Use products_for_ingredients() to identify product
concepts associated with one or more ingredient RxCUIs.
products <- products_for_ingredients(
ingredients$ingredient_rxcui,
concept_status = "active"
)
productsBy default, most workflows should focus on active RxNorm concepts. For studies that span older calendar periods, you may want to include historical concepts as well.
products_historical <- products_for_ingredients(
ingredients$ingredient_rxcui,
concept_status = "active_and_historical"
)
products_historicalHistorical concepts can be useful when reconstructing medication exposure during older study periods. However, some historical concepts may have less complete clinical attribute information than active concepts, so users should review route, dose form, and ingredient information carefully when using historical concepts.
Choose product term types
RxNorm includes several term types, or TTYs, for clinical drugs,
branded drugs, packs, and other related concepts. rxref
provides helpers for common product-focused TTY sets.
product_ttys("default")
product_ttys("extended_product")
product_ttys("extended")For example, you can request an expanded set of product concepts:
products_extended <- products_for_ingredients(
ingredients$ingredient_rxcui,
ttys = product_ttys("extended_product"),
concept_status = "active"
)
products_extendedThe appropriate TTY set depends on the study question. A narrower
product set may be preferable for simple ingredient-to-product
workflows, while an extended set may be useful when users want to
capture additional product or pack concepts. More information on TTYs
can be found by running tty_catalogue().
Search for drugs in one step
For many common workflows, search_drug() provides a
compact interface that combines ingredient search, product expansion,
route filtering, and optional NDC mapping.
For example, to search for oral metformin products:
search_drug(
term = "metformin",
return = "product",
route = "ORAL"
)To return NDCs instead of product concepts:
search_drug(
term = "metformin",
return = "ndc",
route = "ORAL",
ndc_status = "ACTIVE"
)To return both product concepts and NDCs:
search_drug(
term = "metformin",
return = "both",
route = "ORAL",
ndc_status = "ACTIVE"
)For historical studies, you can include historical RxNorm concepts and broader NDC status categories:
search_drug(
term = "metformin",
return = "ndc",
route = "ORAL",
concept_status = "active_and_historical",
ndc_status = c("ACTIVE", "OBSOLETE", "UNSPECIFIED")
)Here, concept_status controls whether active or
historical RxNorm concepts are considered. The ndc_status
argument controls which NDC status categories are returned.
Retrieve clinical attributes
Some workflows require route, dose form, strength, or
ingredient-count information. The get_clinical_attributes()
function retrieves product-level clinical attributes for RxCUIs.
attrs <- get_clinical_attributes(products$product_rxcui)
attrsThese attributes can be useful for route-specific medication lists:
attrs |>
count(routes, dose_form_groups, sort = TRUE)Combination products may include more than one ingredient. Depending on the workflow, users may want to exclude fixed-dose combinations, retain them, or inspect them separately.
attrs |>
filter(n_ingredients > 1)Build route-specific lists
The filter_products_by_route() helper can be used after
product expansion to retain products matching a specified route.
oral_products <- products |>
filter_products_by_route(route = "ORAL")
oral_productsRoute filtering relies on available clinical attribute information. If a product concept lacks route or dose-form information, it may not be retained by route-specific filters. This is especially important when working with historical RxNorm concepts.
Caching and API use
rxref is designed to support vectorized workflows, but
large medication lists can require many API calls. Repeated requests can
be reduced by enabling caching through rxref_conf().
For example, to use an in-memory cache during a session:
rxref_conf(cache = cachem::cache_mem())You can also adjust the delay between API requests:
rxref_conf(rate_delay = 0.2)This can be helpful for large batch workflows or when working interactively with many RxCUIs. But, be kind to the API. RxNorm specifies a maximum request rate of 20 per second per IP.
Reproducibility
The public RxNorm and RxClass APIs reflect current source data and may change over time as RxNorm releases are updated. For strict reproducibility, especially in studies tied to a specific calendar period, users should save the medication lists, product concepts, NDC mappings, and API outputs used in the final analytic workflow.
At some point, a future version of rxref may support
local or release-specific backends for users who need to bind analyses
to specific RxNorm releases.
Summary
rxref supports common medication-identification
workflows, including:
- resolving names, NDCs, or RxCUIs with
resolve(); - retrieving concept metadata with
get_properties(); - mapping between NDCs and RxCUIs with
map_ndc_to_rxcui()andmap_rxcui_to_ndc(); - identifying ingredients with
find_ingredients(); - expanding ingredients to products with
products_for_ingredients(); - retrieving route and dose-form information with
get_clinical_attributes(); - building route-specific product lists with
filter_products_by_route(); - using
search_drug()for compact end-to-end workflows.
These functions are intended to support transparent, reproducible medication list construction while keeping outputs tidy and compatible with common dplyr workflows.
