Skip to content

Add mapping file to map hosp.prescriptions.ndc to various drug classes - #1753

Open
mlbernauer wants to merge 4 commits into
MIT-LCP:mainfrom
mlbernauer:feat-drug-mappings
Open

Add mapping file to map hosp.prescriptions.ndc to various drug classes#1753
mlbernauer wants to merge 4 commits into
MIT-LCP:mainfrom
mlbernauer:feat-drug-mappings

Conversation

@mlbernauer

@mlbernauer mlbernauer commented Jun 8, 2024

Copy link
Copy Markdown
Contributor

This PR adds a mapping file (drug_mappings.csv) which allows drugs in prescriptions table to be organized into different classes (e.g. therapeutic, pharmacologic, mechanism of action, pharmacokinetic, among others).

col_name description
ndc NDC (foreign key into prescriptions table)
rxcui RxNorm CUI corresponding to NDC
relation Relationship between rxcui and maps_to_rxcui
maps_to_name Name of the ingredient the NDC maps to
maps_to_tty RxNorm term type indicating the type of agent the NDC maps to
relation_source Source vocabulary for the mapping
maps_to_rxcui RxNorm CUI of the agent that the NDC maps to
class_type Describes the type of class
class_name Class name
class_id Class ID from the source vocabulary

@mlbernauer

Copy link
Copy Markdown
Contributor Author

In total there appear to be 5732 distinct non-null NDCs in the hosp.prescriptions table, I was able to map each NDC to at least one of the class vocabs, however some vocabs have more coverage than others. Here's a breakdown of how the NDCs from the prescription table map across the different vocabularies available within RxClass

vocab mapped_ndcs total_ndcs fraction_mapped
MEDRT 5152 5732 0.898813677599442
ATCPROD 5119 5732 0.893056524773203
VA 5061 5732 0.882937892533147
ATC 4902 5732 0.85519888346127
SNOMEDCT 4838 5732 0.844033496161898
FDASPL 4353 5732 0.759420795533845
DAILYMED 4331 5732 0.755582693649686
FMTSME 1164 5732 0.203070481507327
NA 579 5732 0.101011863224006
RXNORM 394 5732 0.0687369155617586

@mlbernauer

mlbernauer commented Jun 8, 2024

Copy link
Copy Markdown
Contributor Author

As an example, one can use the ATC classification to query all NDCs for Antiinfectives for Systemic Use which has a top-level ATC classification code of J

select * from [mappings.drug_class] where relation_source like 'ATC%' and class_id like 'J%';

which should return 2109 results (785 distinct NDCs) across both the ATC and ATCPROD vocabularies.

One limitation of this mapping file is that it only contains mappings between drugs and their immediate parent class. In other words, if a drug maps to class A and class A maps to class B there will no be relation between the drug and class B. However, this limitation can be circumvented when using the ATC vocabs since their class_id codes are "semantic identifiers" i.e. they contain information about the class hierarchy which can be exploited as in the example above

@Chessing234

Copy link
Copy Markdown
Contributor

ndc→drug class map is nice. how do you handle obsolete/invalid ndc codes — drop or keep as unknown?

@Chessing234 Chessing234 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i asked about invalid ndcs earlier; having pulled the file apart the format side is fine — every ndc is a quoted 11-digit string with leading zeros preserved, so it joins to hosp.prescriptions.ndc cleanly. no complaints there.

my concern is what the file actually contains versus what the title and body describe. of the 182,774 rows, the relation breakdown is:

38003  may_treat
27104  ci_with
22685  has_pe
19938  (empty)
17081  has_moa
10080  has_epc
 7419  has_ingredient
 ...
 4617  may_prevent

and by class_type, 69,193 rows — 38% of the file — are DISEASE. so the majority of this isn't drug-class membership at all; it's drug-to-disease relations, and 27k of those are contraindications. the very first data row is cycloserine ci_with "Alcoholism".

that's a real trap given how the pr is framed. your own example in the thread (where relation_source like 'ATC%') filters correctly, but the file is named drug_mappings.csv and described as mapping drugs "into different classes", so someone joining on ndc and grouping by class_name without filtering relation will silently treat contraindicated conditions as drug classes. could you either split the therapeutic-class rows from the drug-disease rows, or document the relation and class_type vocabularies in a readme alongside the csv and state plainly that filtering on relation is required?

the 19,938 rows with an empty relation also need explaining — as it stands there's no way to tell whether those are a distinct relation type, an extraction gap, or rows that should have been dropped.

two smaller things: the file is ~22 MB in a single commit, so it'd help to record how it was generated (which RxClass/RxNorm release, retrieved when, with what script) so it can be refreshed rather than becoming a frozen snapshot; and RxNorm/RxClass redistribution terms should probably be acknowledged somewhere. for what it's worth mimic-iv/mapping/ is the right place — d_labitems_to_loinc.csv and friends already live there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants