
Building route-specific RxCUI and NDC lists
Steven Smith
Source:vignettes/route_specific_lists.Rmd
route_specific_lists.RmdOverview
A common use case for rxref is to develop a list of RxNorm product concepts and National Drug Codes (NDCs) for a drug class.
For example, suppose we want to identify product RxCUIs and active NDCs for oral beta-blockers. This is not as simple as searching for beta-blocker ingredients and mapping everything to NDCs, because some beta-blockers are available through multiple routes.
For example:
-
metoprolol,atenolol,labetalol,propranolol, andsotalolmay have oral and injectable products. -
esmololis injectable only. -
timolol,betaxolol, and related drugs may have ophthalmic products.
For many pharmacoepidemiologic studies, we may want oral outpatient-use products only.
This vignette walks through a tidy workflow for:
- resolving drug names to ingredient RxCUIs;
- expanding ingredient RxCUIs to product RxCUIs;
- filtering product RxCUIs by route; and,
- mapping the filtered product RxCUIs to active NDCs.
Define a beta-blocker ingredient list
In this example, we start with generic drug names. In future versions
of rxref, class-level helpers may make this step more
automated. For now, users can supply a curated ingredient list for the
class of interest.
Resolve drug names to ingredient RxCUIs
First, use find_ingredients() to resolve each drug name
to an RxNorm ingredient concept.
bb_ingredients <- find_ingredients(beta_blocker_names) |>
filter(tty == "IN") |>
distinct(
input,
ingredient_rxcui = rxcui,
ingredient_name = name
)
bb_ingredientsThe resulting table contains one row per resolved ingredient. These ingredient RxCUIs are the starting point for product expansion.
Expand ingredients to product RxCUIs
Next, use products_for_ingredients() to identify
product-level RxNorm concepts containing each ingredient.
bb_products <- products_for_ingredients(
bb_ingredients$ingredient_rxcui,
include_combos = TRUE
) |>
left_join(bb_ingredients, by = "ingredient_rxcui")
bb_productsBy default, this returns product-level RxNorm concepts such as
clinical drugs and branded drugs. Because
include_combos = TRUE, combination products are retained.
For beta-blockers, this means products such as beta-blocker/thiazide
combinations may be included.
To exclude combination products, set:
bb_single_ingredient_products <- products_for_ingredients(
bb_ingredients$ingredient_rxcui,
include_combos = FALSE
)
bb_single_ingredient_productsWhy route filtering matters
At this point, the product list may include products from multiple routes. For example, some beta-blockers have oral tablets, injectable products, or ophthalmic solutions.
We can use get_clinical_attributes() to inspect route
information for the product RxCUIs.
bb_attrs <- get_clinical_attributes(
unique(bb_products$product_rxcui)
)
bb_attrs |>
count(route, dose_form_group, sort = TRUE)This helps verify whether the product list includes routes that are outside the intended use case.
Filter to oral products
To keep only orally available products, use
filter_products_by_route().
bb_oral_products <- bb_products |>
filter_products_by_route(route = "ORAL")
bb_oral_productsThe returned table keeps product-level metadata and appends summarized route and dose-form information.
bb_oral_products |>
count(routes, dose_form_groups, sort = TRUE)This should retain products such as oral tablets, capsules, and oral solutions, while excluding injectable or ophthalmic products.
Map oral product RxCUIs to active NDCs
Once the product list is restricted to oral products, use
map_products_to_ndcs() to map the product RxCUIs to
NDCs.
bb_oral_ndcs <- map_products_to_ndcs(
bb_oral_products,
status = "ACTIVE"
)
bb_oral_ndcsThe output is a flat tibble with one row per product RxCUI/NDC pair. Product metadata is retained alongside the NDC.
bb_oral_ndcs |>
select(
ingredient_name,
product_rxcui,
product_name,
product_tty,
routes,
dose_forms,
ndc11,
ndc_status
)Summarize the resulting list
For quality control, it is useful to summarize the number of products and NDCs by ingredient.
bb_oral_products |>
count(ingredient_name, sort = TRUE, name = "n_product_rxcuis")
bb_oral_ndcs |>
count(ingredient_name, sort = TRUE, name = "n_active_ndcs")You may also want to inspect combination products separately.
A shortcut using search_drug()
The same workflow can be run more compactly with
search_drug().
To return oral product RxCUIs only:
bb_oral_rxcuis <- search_drug(
beta_blocker_names,
return = "rxcui",
route = "ORAL",
include_combos = TRUE
)
bb_oral_rxcuisTo return a flat table of oral product RxCUIs and active NDCs:
bb_oral_ndcs2 <- search_drug(
beta_blocker_names,
return = "ndc",
route = "ORAL",
ndc_status = "ACTIVE",
include_combos = TRUE
)
bb_oral_ndcs2This is the most direct workflow when the goal is a usable product RxCUI/NDC table.
Returning both products and NDCs
If you want both the unique product RxCUI table and the expanded NDC
table, use return = "both".
bb_oral_both <- search_drug(
beta_blocker_names,
return = "both",
route = "ORAL",
ndc_status = "ACTIVE",
include_combos = TRUE
)
names(bb_oral_both)
bb_oral_both$products
bb_oral_both$ndcsThis returns a list because the two tables have different grains:
-
products: one row per product RxCUI; -
ndcs: one row per product RxCUI/NDC pair.
Suggested QC checks
When developing a study-specific medication list, it is good practice to review the resulting concepts before finalizing the cohort definition. Even if the package is working correctly, there are on occasion errors in RxNorm itself.
The following are some examples.
Check the observed routes and dose-form groups
bb_oral_products |>
count(routes, dose_form_groups, sort = TRUE)Summary
This vignette demonstrated how to build a route-specific medication
list, with oral beta-blockers as an example, using
rxref.
The key steps are:
-
find_ingredients()to resolve drug names to ingredient RxCUIs; -
products_for_ingredients()to expand ingredients to product RxCUIs; -
filter_products_by_route()to retain products for the route of interest; -
map_products_to_ndcs()to obtain NDCs; OR, -
search_drug()for a compact end-to-end workflow.
For drug classes with products available through multiple routes, route filtering is an important quality-control step before mapping to NDCs or using the resulting list in pharmacoepidemiologic analyses.