Successfully Building Code Lists Using Concepts and OMOP
successfully_building_code_lists_with_concepts.Rmd
Background
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 |
---|---|---|
7da88dce-dffa-4838-84b1-a491d97f9ac5 | MRI of brain with contrast | be5d1373-de77-4b4c-ba18-e7946114919e |
a9f5287e-b0f2-494f-b4f5-95812ca193d4 | MRI of orbit with contrast | 567e303b-9106-436f-bace-4b30a0b59ded |
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 |