The objective for this exercise is to introduce you to the basic mechanisms for working with FHIR.
For this exercise, we will walk you through the following steps:
We will use the fhircrackr
library to handle querying from a FHIR server and converting the response into an R dataframe.
Let’s get our environment set up:
library(fhircrackr)
First let’s connect to our FHIR server for data retrieval.
Generally speaking the pattern for a RESTful GET query appended to a URL will take the form of:
VERB [url]/[Resource] {?parameter=[value]}
See http://hl7.org/fhir/R4/http.html for more details.
Let’s attempt to do a sample load from our example FHIR server by requesting Patient resources for the available patients.
In this case, we want to modify the general pattern with:
[url] = https://api.logicahealth.org/researchonfhir/open/
[Resource] = Patient
fhir_server <- "https://api.logicahealth.org/researchonfhir/open/"
request <- fhir_url(url = fhir_server, resource = "Patient")
patient_bundle <- fhir_search(request = request, max_bundles = 1, verbose = 1)
## Starting download of 1 bundles of resource type https://api.logicahealth.org/researchonfhir/open/Patient from FHIR base URL https://api.logicahealth.org/researchonfhir/open/Patient.
##
## Download completed. Number of downloaded bundles was limited to 1 bundles, this is less than the total number of bundles available.
patient_bundle
## An object of class "fhir_bundle_list"
## [[1]]
## A fhir_bundle_xml object
## No. of entries : 50
## Self Link: https://api.logicahealth.org/researchonfhir/open/Patient
## Next Link: https://api.logicahealth.org/researchonfhir/open?_getpages=ac415e48-23bf-4700-9f57-36069b6aef9d&_getpagesoffset=50&_count=50&_pretty=true&_bundletype=searchset
##
## {xml_node}
## <Bundle>
## [1] <id value="ac415e48-23bf-4700-9f57-36069b6aef9d"/>
## [2] <meta>\n <lastUpdated value="2022-03-10T11:42:45.470+00:00"/>\n</meta>
## [3] <type value="searchset"/>
## [4] <total value="70"/>
## [5] <link>\n <relation value="self"/>\n <url value="https://api.logicaheal ...
## [6] <link>\n <relation value="next"/>\n <url value="https://api.logicaheal ...
## [7] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [8] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [9] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [10] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [11] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [12] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [13] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [14] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [15] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [16] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [17] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [18] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [19] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## [20] <entry>\n <fullUrl value="https://api.logicahealth.org/researchonfhir/o ...
## ...
If the above request works, you should see a preview of the first few lines of XML representing the FHIR resources from patient_bundle
above.
The fhircrackr
library uses the fhir_table_description()
function to translate the hierarchical XML resource returned by the FHIR server into a tabular format (i.e., a data frame) that works with typical analysis approaches in R.
This function creates a definition mapping parts of the XML representation of the resource onto columns in the data frame that will be generated. The XML elements are identified using XPath, a query language for XML.
table_desc_patient <- fhir_table_description(
resource = "Patient",
cols = c(
id = "id",
given_name = "name/given",
family_name = "name/family",
gender = "gender",
birthday = "birthDate",
birthTime = "extension[@url=\"http://hl7.org/fhir/StructureDefinition/patient-birthTime\"]/valueDateTime"
)
)
Many of the XPath queries you will use wil be straight-forward, like id
and name/given
. In some cases, you may need to construct more complex queries like the one to extract birthTime
from the patient-birthTime
extension in the FHIR resource instance. You can use a tool like this XPath tester to help generate XPaths. For more information on XPath, see this guide.
Once the table description is created, we can create a data frame:
df_patient <- fhir_crack(bundles = patient_bundle, design = table_desc_patient, verbose = 0)
## Warning in fhir_crack(bundles = patient_bundle, design = table_desc_patient, : In the cols element of the design, you specified XPath expressions containing '//' which point to an arbitrary level in the resource.
## This can result in unexpected behaviour, e.g. when the searched element appears on different levels of the resource.
## We strongly advise to only use the fully specified relative XPath in the cols element, e.g. 'ingredient/strength/numerator/code' instead of search paths like '//code'.
## This warning is thrown for the following data.frame descriptions: birthTime
df_patient
You should see the name, gender, birthday and birth time for 50 patients.