fhiRclient.Rmd
The R package is developed to implement the FHIR client with essential features of authentication, CRUD operations, bundle search, and data structures for the FHIR resources. The package is built based on the python library fhircient
and S4 class. Tidy-style functions were developed for the clinial data manipulation more friendly.
To get started, first we need to load the package.
library(fhiRclient)
#> Loading required package: reticulate
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
The dependent python fhirclient
can be installed from the build-in method. The latest version can be installed from its github repository directly for the version of R4 support.
install_fhirclient(version = "latest")
ct <- Client(app_id = "my_app",
api_base = "https://r4.smarthealthit.org")
ct
#> <class 'fhirclient.client.FHIRClient'>
#> length: 21
#> names: app_id app_secret authorize_url ...
To read a patient record and convert it to json list.
pt <- Patient(list(id = "326b4675-0bc8-4dbd-b406-a5564c282401"))
ct %>% Read(pt) %>% as_json %>% as_json_tbl
#> # A tibble: 88 x 2
#> name value
#> <chr> <chr>
#> 1 id 326b4675-0bc8-4dbd-b406-a5564c282401
#> 2 meta.lastUpdated 2020-11-18T02:05:08.474-05:00
#> 3 meta.tag.code synthea-5-2019
#> 4 meta.tag.system https://smarthealthit.org/tags
#> 5 meta.versionId 16
#> 6 extension.extension.url ombCategory
#> 7 extension.extension.valueCoding.code 2106-3
#> 8 extension.extension.valueCoding.display White
#> 9 extension.extension.valueCoding.system urn:oid:2.16.840.1.113883.6.238
#> 10 extension.extension.url text
#> # … with 78 more rows
To read a patient and get the birth date.
ct %>% Read(pt) %>% BirthDate
#> [1] "1991-07-20"
To read a patient and get the full name.
ct %>% Read(pt) %>% getName
#> [[1]]
#> [1] "Mr. Bradly Douglas"
ct %>% Delete(pt1)
#> $resourceType
#> [1] "OperationOutcome"
#>
#> $issue
#> $issue[[1]]
#> $issue[[1]]$severity
#> [1] "information"
#>
#> $issue[[1]]$code
#> [1] "informational"
#>
#> $issue[[1]]$diagnostics
#> [1] "Successfully deleted 1 resource(s) in 7ms"
The Search
function can be used to search for resource bundles with parameters. The page
option can be specified to look up results from first page or all pages.
res <- Search(ct, "observation", "Observation",
list(code = "http://loinc.org|2339-0"), page = "all")
res
#> # A tibble: 88,640 x 2
#> name value
#> <chr> <chr>
#> 1 id 9b41529c-8e1d-4c2e-adf7-840bf47c5216
#> 2 meta.lastUpdated 2020-11-25T21:55:54.111-05:00
#> 3 entry.fullUrl https://r4.smarthealthit.org/Observation/a8dbb860…
#> 4 entry.resource.id a8dbb860-4190-46da-af7b-11bf7c7f9ffd
#> 5 entry.resource.meta.lastU… 2019-06-06T02:51:24.277-04:00
#> 6 entry.resource.meta.tag.c… synthea-5-2019
#> 7 entry.resource.meta.tag.s… https://smarthealthit.org/tags
#> 8 entry.resource.meta.versi… 3
#> 9 entry.resource.category.c… laboratory
#> 10 entry.resource.category.c… laboratory
#> # … with 88,630 more rows
The filterBundle
function can be used to extract specific elements. For example, here we extract all the unique reference patients.
res %>% filterBundle('subject') %>% unique
#> # A tibble: 269 x 2
#> name value
#> <chr> <chr>
#> 1 entry.resource.subject.reference Patient/948e608d-e408-4788-8cf2-8157c49c2940
#> 2 entry.resource.subject.reference Patient/d48ac962-78c6-46cf-ba33-a24771bfa0e4
#> 3 entry.resource.subject.reference Patient/4d58465c-4703-4c36-ab8f-2f935dc4bee7
#> 4 entry.resource.subject.reference Patient/0ac13d55-d566-450a-aea0-f6a71f1ad73b
#> 5 entry.resource.subject.reference Patient/ecaea95c-46de-4ac9-a58d-4847d1a3e574
#> 6 entry.resource.subject.reference Patient/63c5db14-f5b0-4405-9ff6-0b88601ddb22
#> 7 entry.resource.subject.reference Patient/b218cee9-019d-47a4-b161-e97c0fd6f736
#> 8 entry.resource.subject.reference Patient/32cd9fa4-7a32-4de1-bce2-548e37151540
#> 9 entry.resource.subject.reference Patient/2a86d65b-06c7-4100-9d43-948921b49605
#> 10 entry.resource.subject.reference Patient/6bb3d38f-ae2e-40cf-a31e-baaea0b8bcc1
#> # … with 259 more rows
We can group the results with indexes and convert it to wide table with patients in different columns.
gres <- res %>% filterBundle("entry.resource") %>% group_index("entry.resource.id")
gres
#> # A tibble: 74,405 x 3
#> # Groups: entry.resource.id [3,383]
#> name value entry.resource.id
#> <chr> <chr> <chr>
#> 1 entry.resource.id a8dbb860-4190-46da-af7b-11bf… a8dbb860-4190-46da-af7b-…
#> 2 entry.resource.meta.… 2019-06-06T02:51:24.277-04:00 a8dbb860-4190-46da-af7b-…
#> 3 entry.resource.meta.… synthea-5-2019 a8dbb860-4190-46da-af7b-…
#> 4 entry.resource.meta.… https://smarthealthit.org/ta… a8dbb860-4190-46da-af7b-…
#> 5 entry.resource.meta.… 3 a8dbb860-4190-46da-af7b-…
#> 6 entry.resource.categ… laboratory a8dbb860-4190-46da-af7b-…
#> 7 entry.resource.categ… laboratory a8dbb860-4190-46da-af7b-…
#> 8 entry.resource.categ… http://terminology.hl7.org/C… a8dbb860-4190-46da-af7b-…
#> 9 entry.resource.code.… 2339-0 a8dbb860-4190-46da-af7b-…
#> 10 entry.resource.code.… Glucose a8dbb860-4190-46da-af7b-…
#> # … with 74,395 more rows
gres[1:44,] %>% tidyr::pivot_wider(names_from = entry.resource.id)
#> # A tibble: 22 x 3
#> name `a8dbb860-4190-46da-af7b-11bf… `0c115a64-8e55-411c-bcc3-afe…
#> <chr> <chr> <chr>
#> 1 entry.resource.… a8dbb860-4190-46da-af7b-11bf7… 0c115a64-8e55-411c-bcc3-afee…
#> 2 entry.resource.… 2019-06-06T02:51:24.277-04:00 2019-06-06T02:51:27.094-04:00
#> 3 entry.resource.… synthea-5-2019 synthea-5-2019
#> 4 entry.resource.… https://smarthealthit.org/tags https://smarthealthit.org/ta…
#> 5 entry.resource.… 3 3
#> 6 entry.resource.… laboratory laboratory
#> 7 entry.resource.… laboratory laboratory
#> 8 entry.resource.… http://terminology.hl7.org/Co… http://terminology.hl7.org/C…
#> 9 entry.resource.… 2339-0 2339-0
#> 10 entry.resource.… Glucose Glucose
#> # … with 12 more rows
Here we have two ways to create a patient model, with Patient
functon or a general Model
constructor.
The function getModelClass
can be used to query all available classes for a model. The general Model
function require the resource model name and a data class to build.
getModelClass("humanname")
#> $HumanName
#> <class 'fhirclient.models.humanname.HumanName'>
hn <- Model("humanname", "HumanName", list(family = "A", given = list("B", "C")))
hn
#> <class 'fhirclient.models.humanname.HumanName'>
#> length: 19
#> names: as_json didResolveReference elementProperties ...
as_json(hn)
#> $family
#> [1] "A"
#>
#> $given
#> [1] "B" "C"
sessionInfo()
#> R version 4.0.2 (2020-06-22)
#> Platform: x86_64-apple-darwin19.6.0 (64-bit)
#> Running under: macOS 10.16
#>
#> Matrix products: default
#> BLAS/LAPACK: /Users/qi28068/homebrew/Cellar/openblas/0.3.10_1/lib/libopenblasp-r0.3.10.dylib
#>
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] dplyr_1.0.2 fhiRclient_0.0.1 reticulate_1.18
#>
#> loaded via a namespace (and not attached):
#> [1] Rcpp_1.0.5 later_1.1.0.1 compiler_4.0.2 pillar_1.4.7
#> [5] tools_4.0.2 digest_0.6.27 jsonlite_1.7.1 evaluate_0.14
#> [9] memoise_1.1.0 lifecycle_0.2.0 tibble_3.0.4 lattice_0.20-41
#> [13] pkgconfig_2.0.3 rlang_0.4.8 Matrix_1.2-18 cli_2.2.0
#> [17] shiny_1.5.0 curl_4.3 yaml_2.2.1 pkgdown_1.6.1
#> [21] xfun_0.19 fastmap_1.0.1 httr_1.4.2 stringr_1.4.0
#> [25] knitr_1.30 desc_1.2.0 generics_0.1.0 fs_1.5.0
#> [29] vctrs_0.3.5 systemfonts_0.3.2 rprojroot_2.0.2 grid_4.0.2
#> [33] tidyselect_1.1.0 glue_1.4.2 R6_2.5.0 textshaping_0.2.1
#> [37] fansi_0.4.1 rmarkdown_2.5 tidyr_1.1.2 purrr_0.3.4
#> [41] magrittr_2.0.1 promises_1.1.1 htmltools_0.5.0 ellipsis_0.3.1
#> [45] assertthat_0.2.1 xtable_1.8-4 mime_0.9 httpuv_1.5.4
#> [49] ragg_0.4.0 utf8_1.1.4 stringi_1.5.3 crayon_1.3.4