Mapping Entities with Corresponding NDC Codes

Description

This model maps drug entities extracted from clinical text to their corresponding National Drug Codes (NDC). It uses ner_posology_greedy for drug entity recognition and provides fast code mapping without requiring embeddings at inference time. Trained on the openFDA NDC Directory (release 2026-07-22).

Live Demo Open in Colab Copy S3 URI

How to use


document_assembler = DocumentAssembler()\
    .setInputCol("text")\
    .setOutputCol("document")

sentence_detector = SentenceDetector()\
    .setInputCols(["document"])\
    .setOutputCol("sentence")

tokenizer = Tokenizer()\
    .setInputCols(["sentence"])\
    .setOutputCol("token")

word_embeddings = WordEmbeddingsModel.pretrained("embeddings_clinical", "en", "clinical/models")\
    .setInputCols(["sentence", "token"])\
    .setOutputCol("embeddings")

ner_posology = MedicalNerModel.pretrained("ner_posology_greedy", "en", "clinical/models")\
    .setInputCols(["sentence", "token", "embeddings"])\
    .setOutputCol("posology_ner")

ner_posology_converter = NerConverterInternal()\
    .setInputCols(["sentence", "token", "posology_ner"])\
    .setOutputCol("ner_chunk")\
    .setWhiteList(["DRUG"])

ndc_mapper = ChunkMapperModel.pretrained("ndc_mapper", "en", "clinical/models")\
    .setInputCols(["ner_chunk"])\
    .setOutputCol("mappings")\
    .setRels(["ndc_code"])

pipeline = Pipeline(stages=[
    document_assembler, sentence_detector, tokenizer, word_embeddings,
    ner_posology, ner_posology_converter, ndc_mapper
])
data = spark.createDataFrame([["She was started on amoxicillin 500 mg three times daily for a bacterial sinus infection, continues aspirin 81 mg once daily for cardiovascular prophylaxis, takes acetaminophen 500 mg as needed for pain, and was also prescribed cetirizine hydrochloride 10 mg once daily for seasonal allergies."]]).toDF("text")
result = pipeline.fit(data).transform(data)


document_assembler = nlp.DocumentAssembler()\
    .setInputCol("text")\
    .setOutputCol("document")

sentence_detector = nlp.SentenceDetector()\
    .setInputCols(["document"])\
    .setOutputCol("sentence")

tokenizer = nlp.Tokenizer()\
    .setInputCols(["sentence"])\
    .setOutputCol("token")

word_embeddings = nlp.WordEmbeddingsModel.pretrained("embeddings_clinical", "en", "clinical/models")\
    .setInputCols(["sentence", "token"])\
    .setOutputCol("embeddings")

ner_posology = medical.NerModel.pretrained("ner_posology_greedy", "en", "clinical/models")\
    .setInputCols(["sentence", "token", "embeddings"])\
    .setOutputCol("posology_ner")

ner_posology_converter = medical.NerConverterInternal()\
    .setInputCols(["sentence", "token", "posology_ner"])\
    .setOutputCol("ner_chunk")\
    .setWhiteList(["DRUG"])

ndc_mapper = medical.ChunkMapperModel.pretrained("ndc_mapper", "en", "clinical/models")\
    .setInputCols(["ner_chunk"])\
    .setOutputCol("mappings")\
    .setRels(["ndc_code"])

pipeline = nlp.Pipeline(stages=[
    document_assembler, sentence_detector, tokenizer, word_embeddings,
    ner_posology, ner_posology_converter, ndc_mapper
])
data = spark.createDataFrame([["She was started on amoxicillin 500 mg three times daily for a bacterial sinus infection, continues aspirin 81 mg once daily for cardiovascular prophylaxis, takes acetaminophen 500 mg as needed for pain, and was also prescribed cetirizine hydrochloride 10 mg once daily for seasonal allergies."]]).toDF("text")
result = pipeline.fit(data).transform(data)


val documentAssembler = new DocumentAssembler()
    .setInputCol("text")
    .setOutputCol("document")

val sentenceDetector = new SentenceDetector()
    .setInputCols("document")
    .setOutputCol("sentence")

val tokenizer = new Tokenizer()
    .setInputCols("sentence")
    .setOutputCol("token")

val wordEmbeddings = WordEmbeddingsModel.pretrained("embeddings_clinical", "en", "clinical/models")
    .setInputCols(Array("sentence", "token"))
    .setOutputCol("embeddings")

val nerPosology = MedicalNerModel.pretrained("ner_posology_greedy", "en", "clinical/models")
    .setInputCols(Array("sentence", "token", "embeddings"))
    .setOutputCol("posology_ner")

val nerPosologyConverter = new NerConverterInternal()
    .setInputCols(Array("sentence", "token", "posology_ner"))
    .setOutputCol("ner_chunk")
    .setWhiteList(Array("DRUG"))

val ndcMapper = ChunkMapperModel.pretrained("ndc_mapper", "en", "clinical/models")
    .setInputCols(Array("ner_chunk"))
    .setOutputCol("mappings")
    .setRels(Array("ndc_code"))

val pipeline = new Pipeline().setStages(Array(
    documentAssembler, sentenceDetector, tokenizer, wordEmbeddings,
    nerPosology, nerPosologyConverter, ndcMapper
))

val data = Seq("She was started on amoxicillin 500 mg three times daily for a bacterial sinus infection, continues aspirin 81 mg once daily for cardiovascular prophylaxis, takes acetaminophen 500 mg as needed for pain, and was also prescribed cetirizine hydrochloride 10 mg once daily for seasonal allergies.").toDF("text")
val result = pipeline.fit(data).transform(data)

Results

| ner_chunk                      | ndc_code   |
|:-------------------------------|:-----------|
| amoxicillin 500 mg             | 83112-0500 |
| aspirin 81 mg                  | 41250-0780 |
| acetaminophen 500 mg           | 69618-0011 |
| cetirizine hydrochloride 10 mg | 66424-0564 |

Model Information

Model Name: ndc_mapper
Compatibility: Healthcare NLP 6.4.0+
License: Licensed
Edition: Official
Input Labels: [ner_chunk]
Output Labels: [mappings]
Language: en
Size: 8.3 MB