Successfully Building Code Lists Using Concepts and OMOP
successfully_building_code_lists_with_concepts.RmdBackground
PicnicHealth utilizes OMOP, or the Observational Medical Outcomes Partnership Common Data Model, as the basis of our data model. Clinical concepts in PicnicHealth datasets are mapped to a concept in the OMOP data model.
The OMOP data model can make analyzing the dataset easier by helping
you discover hierachical relationships between concepts rather than
developing exhaustive code lists. The concept tables in your
PicnicHealth dataset - concept,
concept_ancestor, and concept_relationship,
and drug_to_ingredient_map - provide the ontological
information you need to build code lists.
Below, we show two examples - one for medications, and one for procedures.
Note that special considerations for building code lists apply in the conditions domain depending on the date that your dataset was created; see the vignette “ICD and SNOMED codes for clinical conditions” for more details.
Identifying medications from an active ingredient
In OMOP and the PicnicHealth dataset, medications are coded in the RxNorm ontology.
The drug_to_ingredient_map table provides a convenient
mapping of drug names to their primary active ingredient. This is
derived from the concept_ancestor table. This enables you
to easily find all brand names and dose forms with a shared active
ingredient that may appear in medical records.
[1] Use a tool such as OHDSI’s Athena or RxNav to find an ingredient of interest. In this example, we’ll look for drugs with the active ingredient acetaminophen (RxNorm 161).
[2] Load up the PicnicHealth package, and the data
provided.
library(PicnicHealth)
library(dplyr)
data_set = load_data_set(data_path)
list2env(data_set, envir = .GlobalEnv)[3] Filter the concept table to rows where
domain_concept_code = 161 and the vocabulary = RxNorm.
[4] Inner join this filtered table to the
drug_to_ingredient_map table (fields to join:
concept_id ←→ ingredient_concept_id).
aceta_descendants = aceta_concept %>%
inner_join(drug_to_ingredient_map,
by = c("concept_id" = "ingredient_concept_id"))[4] Join this filtered table to
visit_medication_list_occurrence on the field
drug_concept_id to find all relevant treatments.
aceta_meds_list = aceta_descendants %>%
inner_join(visit_medication_list_occurrence,
by = c("drug_concept_id", "drug_concept_name")) %>%
select(visit_medication_list_occurrence_id,
ingredient_concept_name, drug_concept_name,
visit_id)| visit_medication_list_occurrence_id | ingredient_concept_name | drug_concept_name | visit_id |
|---|---|---|---|
| 1f789e24-355d-4be2-8862-5adfe96a7d92 | Acetaminophen | Vicodin | b467be29-0ad4-41e7-9d25-52abee680e4d |
| d53e5d7e-ad39-4b47-a2a7-d484465e7865 | Acetaminophen | Tylenol | 3113ba0b-deb2-4230-a04c-05e3bfbfb373 |
| c33d0f47-480f-4725-b1f2-6cd83ab728a7 | Acetaminophen | Mapap | ce45804a-d12f-4306-8157-533c9ec70691 |
| 61765483-35af-44aa-8a49-02c268bc15de | Acetaminophen | Excedrin | 7e0fcfe6-0da4-4223-bbc4-95d9f963d5a9 |
| ee3b299a-a061-4312-926c-d5371d45a6ca | Acetaminophen | Percocet | 73379f61-a742-4356-9eee-8f2c88f3f434 |
| bfb854d7-683a-4e63-aece-45c91f2100dd | Acetaminophen | Tylenol with Codeine | bb28327a-a1a8-4e36-9deb-f57b2d0d776e |
Identifying procedures with a common ancestor
Note that procedures are rarely coded in procedure reports, and when
they are it is to CPT codes, which we do not capture. PicnicHealth
abstractors instead map procedures to SNOMED codes, which you will find
in the procedure_occurrence and (if applicable to your
dataset) cohort_procedure_occurrence tables.
[1] Use OHDSI’s Athena search tool to inspect the OMOP code lists for your concept of interest. In this example, we’ll look for instances of MRI of head, SNOMED code 241601008, and all concepts falling under it.
[2] Load up the PicnicHealth package, and the data
provided.
library(PicnicHealth)
library(dplyr)
data_set = load_data_set(data_path)
list2env(data_set, envir = .GlobalEnv)[3] Filter the concept table to rows where
domain_concept_code = 241601008
mri_of_head_concept = concept %>%
filter(domain_concept_code == "241601008" &
vocabulary == "Systematic Nomenclature of Medicine - Clinical Terms (IHTSDO)")[4] Inner join this filtered table to the
concept_ancestor table (fields to join: concept_id
←→ ancestor_concept_id).
mri_of_head_descendants = mri_of_head_concept %>%
inner_join(concept_ancestor,
by = c("concept_id" = "ancestor_concept_id"))[4] Join this filtered table to procedure (fields to
join: descendant_concept_id ←→ procedure_concept_id)
to find all instances where a descendant concept of “MRI of head” was
present in a patient’s medical record.
mri_of_head_procedures = mri_of_head_descendants %>%
inner_join(procedure_occurrence,
by = c("descendant_concept_id" = "procedure_concept_id")) %>%
select(procedure_occurrence_id, procedure_concept_name, visit_id)| procedure_occurrence_id | procedure_concept_name | visit_id |
|---|---|---|
| 96162997-dcca-434c-abb5-5db15493a677 | MRI of sella turcica without contrast | 6301b76a-1b10-4134-9de1-c6970a899539 |
| 0e23c2f8-7f02-4fa9-80aa-e99aa0084dc7 | MRI of brain without contrast | 7e7698ed-fe8f-409e-b9f0-11ccb994d158 |
| a9f5287e-b0f2-494f-b4f5-95812ca193d4 | MRI of orbit with contrast | 567e303b-9106-436f-bace-4b30a0b59ded |
| 7da88dce-dffa-4838-84b1-a491d97f9ac5 | MRI of brain with contrast | be5d1373-de77-4b4c-ba18-e7946114919e |