From a8fb75eea80721848851c51a08b4190efac23b23 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:04:32 +0000 Subject: [PATCH 01/25] Add github action to knit Rmd --- .github/workflows/knit-rmd.yaml | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/knit-rmd.yaml diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml new file mode 100644 index 0000000..2872350 --- /dev/null +++ b/.github/workflows/knit-rmd.yaml @@ -0,0 +1,47 @@ +name: Knit Rmd Files + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + knit: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up R + uses: r-lib/actions/setup-r@v2 + + - name: Install dependencies + run: | + Rscript -e 'install.packages(c("rmarkdown", "knitr"))' + + - name: Find and knit Rmd files + run: | + Rscript -e ' + rmd_files <- list.files(pattern = "\\.Rmd$", recursive = TRUE) + for (file in rmd_files) { + rmarkdown::render(file) + } + ' + + - name: Commit changes + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m "Knit Rmd files" || echo "No changes to commit" + + - name: Push changes + uses: ad-m/github-push-action@v0.8.0 + with: + branch: ${{ github.head_ref }} From ce8e2b49f71131d25a405c2f888f64abd74845c1 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:12:54 +0000 Subject: [PATCH 02/25] Update Rmd to test out action --- .../02-omop-walkthrough-critical-care.Rmd | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd b/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd index 044b0bb..30c80cc 100644 --- a/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd +++ b/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd @@ -19,6 +19,10 @@ knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE) ``` ## Installing & loading required packages + +If any of the `library($PACKAGE)` packages aren't installed, you can install them by running `install.packages("$PACKAGE")`, +replacing `$PACKAGE` with the package name. + ```{r packages} # install omopcept from Github if not installed @@ -55,10 +59,10 @@ if (! file.exists(file.path(destdata,"person.csv"))) { # Make GitHub API request to list contents of given path response <- gh::gh(glue::glue("/repos/{repo}/contents/{path}")) - + # Download all files to the destination dir purrr::walk(response, ~ download.file(.x$download_url, destfile = file.path(destdata, .x$name))) - + list.files(destdata) } From 0814e921f1f07951c9c667ccd0af528fb0cbf57b Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:19:15 +0000 Subject: [PATCH 03/25] Add Pandoc --- .github/workflows/knit-rmd.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index 2872350..0ee3296 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -15,6 +15,9 @@ jobs: pull-requests: write steps: + - name: Install pandoc + uses: pandoc/actions/setup@v1 + - name: Checkout repository uses: actions/checkout@v4 From e2bcc5add46bacf7b0d852db05f8660424df6e78 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:27:07 +0000 Subject: [PATCH 04/25] Use r-lib actions for pandoc install --- .github/workflows/knit-rmd.yaml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index 0ee3296..6757502 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -15,9 +15,6 @@ jobs: pull-requests: write steps: - - name: Install pandoc - uses: pandoc/actions/setup@v1 - - name: Checkout repository uses: actions/checkout@v4 @@ -25,6 +22,13 @@ jobs: uses: r-lib/actions/setup-r@v2 - name: Install dependencies + uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: | + any::rmarkdown + any::knitr + install-pandoc: true + - run: | Rscript -e 'install.packages(c("rmarkdown", "knitr"))' From 333ed9a2ff8c1e55c149ba943667aca32e7aef88 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:29:58 +0000 Subject: [PATCH 05/25] Use r-lib actions for pandoc install --- .github/workflows/knit-rmd.yaml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index 6757502..e8328a9 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -15,6 +15,9 @@ jobs: pull-requests: write steps: + - name: Setup pandoc + uses: r-lib/actions/setup-pandoc@v2 + - name: Checkout repository uses: actions/checkout@v4 @@ -22,13 +25,6 @@ jobs: uses: r-lib/actions/setup-r@v2 - name: Install dependencies - uses: r-lib/actions/setup-r-dependencies@v2 - with: - extra-packages: | - any::rmarkdown - any::knitr - install-pandoc: true - - run: | Rscript -e 'install.packages(c("rmarkdown", "knitr"))' From 800679937439b914e21c9b900f796a52d5070966 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:42:30 +0000 Subject: [PATCH 06/25] Try installing omopcept in deps --- .github/workflows/knit-rmd.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index e8328a9..8af95ce 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -26,7 +26,7 @@ jobs: - name: Install dependencies run: | - Rscript -e 'install.packages(c("rmarkdown", "knitr"))' + Rscript -e 'install.packages(c("rmarkdown", "knitr")); remotes::install_github("SAFEHR-data/omopcept")' - name: Find and knit Rmd files run: | From 4fd4ea327456ff3f78de5639b4e01d6d6dec0878 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:46:10 +0000 Subject: [PATCH 07/25] Add renv --- .Rprofile | 1 + renv.lock | 1051 ++++++++++++++++++++++++++++++++++++++ renv/.gitignore | 7 + renv/activate.R | 1220 ++++++++++++++++++++++++++++++++++++++++++++ renv/settings.json | 19 + 5 files changed, 2298 insertions(+) create mode 100644 .Rprofile create mode 100644 renv.lock create mode 100644 renv/.gitignore create mode 100644 renv/activate.R create mode 100644 renv/settings.json diff --git a/.Rprofile b/.Rprofile new file mode 100644 index 0000000..81b960f --- /dev/null +++ b/.Rprofile @@ -0,0 +1 @@ +source("renv/activate.R") diff --git a/renv.lock b/renv.lock new file mode 100644 index 0000000..e67dc3a --- /dev/null +++ b/renv.lock @@ -0,0 +1,1051 @@ +{ + "R": { + "Version": "4.4.2", + "Repositories": [ + { + "Name": "CRAN", + "URL": "https://packagemanager.posit.co/cran/latest" + } + ] + }, + "Packages": { + "MASS": { + "Package": "MASS", + "Version": "7.3-61", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "methods", + "stats", + "utils" + ], + "Hash": "0cafd6f0500e5deba33be22c46bf6055" + }, + "Matrix": { + "Package": "Matrix", + "Version": "1.7-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "grid", + "lattice", + "methods", + "stats", + "utils" + ], + "Hash": "5122bb14d8736372411f955e1b16bc8a" + }, + "R6": { + "Package": "R6", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "470851b6d5d0ac559e9d01bb352b4021" + }, + "RColorBrewer": { + "Package": "RColorBrewer", + "Version": "1.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "45f0398006e83a5b10b72a90663d8d8c" + }, + "askpass": { + "Package": "askpass", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "sys" + ], + "Hash": "cad6cf7f1d5f6e906700b9d3e718c796" + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "543776ae6848fde2f48ff3816d0628bc" + }, + "bit": { + "Package": "bit", + "Version": "4.5.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "f89f074e0e49bf1dbe3eba0a15a91476" + }, + "bit64": { + "Package": "bit64", + "Version": "4.5.2", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "bit", + "methods", + "stats", + "utils" + ], + "Hash": "e84984bf5f12a18628d9a02322128dfd" + }, + "bslib": { + "Package": "bslib", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "cachem", + "fastmap", + "grDevices", + "htmltools", + "jquerylib", + "jsonlite", + "lifecycle", + "memoise", + "mime", + "rlang", + "sass" + ], + "Hash": "b299c6741ca9746fb227debcb0f9fb6c" + }, + "cachem": { + "Package": "cachem", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "fastmap", + "rlang" + ], + "Hash": "cd9a672193789068eb5a2aad65a0dedf" + }, + "cli": { + "Package": "cli", + "Version": "3.6.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "b21916dd77a27642b447374a5d30ecf3" + }, + "clipr": { + "Package": "clipr", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "3f038e5ac7f41d4ac41ce658c85e3042" + }, + "colorspace": { + "Package": "colorspace", + "Version": "2.1-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "methods", + "stats" + ], + "Hash": "d954cb1c57e8d8b756165d7ba18aa55a" + }, + "cpp11": { + "Package": "cpp11", + "Version": "0.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "9df43854f1c84685d095ed6270b52387" + }, + "crayon": { + "Package": "crayon", + "Version": "1.5.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "methods", + "utils" + ], + "Hash": "859d96e65ef198fd43e82b9628d593ef" + }, + "curl": { + "Package": "curl", + "Version": "5.2.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "8f27335f2bcff4d6035edcc82d7d46de" + }, + "digest": { + "Package": "digest", + "Version": "0.6.37", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "33698c4b3127fc9f506654607fb73676" + }, + "dplyr": { + "Package": "dplyr", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "generics", + "glue", + "lifecycle", + "magrittr", + "methods", + "pillar", + "rlang", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "fedd9d00c2944ff00a0e2696ccf048ec" + }, + "evaluate": { + "Package": "evaluate", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "3fd29944b231036ad67c3edb32e02201" + }, + "fansi": { + "Package": "fansi", + "Version": "1.0.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "utils" + ], + "Hash": "962174cf2aeb5b9eea581522286a911f" + }, + "farver": { + "Package": "farver", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "680887028577f3fa2a81e410ed0d6e42" + }, + "fastmap": { + "Package": "fastmap", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "aa5e1cd11c2d15497494c5292d7ffcc8" + }, + "fontawesome": { + "Package": "fontawesome", + "Version": "0.5.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "htmltools", + "rlang" + ], + "Hash": "bd1297f9b5b1fc1372d19e2c4cd82215" + }, + "fs": { + "Package": "fs", + "Version": "1.6.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "15aeb8c27f5ea5161f9f6a641fafd93a" + }, + "generics": { + "Package": "generics", + "Version": "0.1.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "15e9634c0fcd294799e9b2e929ed1b86" + }, + "ggplot2": { + "Package": "ggplot2", + "Version": "3.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "MASS", + "R", + "cli", + "glue", + "grDevices", + "grid", + "gtable", + "isoband", + "lifecycle", + "mgcv", + "rlang", + "scales", + "stats", + "tibble", + "vctrs", + "withr" + ], + "Hash": "44c6a2f8202d5b7e878ea274b1092426" + }, + "gh": { + "Package": "gh", + "Version": "1.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "gitcreds", + "glue", + "httr2", + "ini", + "jsonlite", + "lifecycle", + "rlang" + ], + "Hash": "fbbbc48eba7a6626a08bb365e44b563b" + }, + "gitcreds": { + "Package": "gitcreds", + "Version": "0.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "ab08ac61f3e1be454ae21911eb8bc2fe" + }, + "glue": { + "Package": "glue", + "Version": "1.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "5899f1eaa825580172bb56c08266f37c" + }, + "gtable": { + "Package": "gtable", + "Version": "0.3.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "grid", + "lifecycle", + "rlang", + "stats" + ], + "Hash": "de949855009e2d4d0e52a844e30617ae" + }, + "here": { + "Package": "here", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "rprojroot" + ], + "Hash": "24b224366f9c2e7534d2344d10d59211" + }, + "highr": { + "Package": "highr", + "Version": "0.11", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "xfun" + ], + "Hash": "d65ba49117ca223614f71b60d85b8ab7" + }, + "hms": { + "Package": "hms", + "Version": "1.1.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "lifecycle", + "methods", + "pkgconfig", + "rlang", + "vctrs" + ], + "Hash": "b59377caa7ed00fa41808342002138f9" + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.8.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "digest", + "fastmap", + "grDevices", + "rlang", + "utils" + ], + "Hash": "81d371a9cc60640e74e4ab6ac46dcedc" + }, + "httr2": { + "Package": "httr2", + "Version": "1.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "curl", + "glue", + "lifecycle", + "magrittr", + "openssl", + "rappdirs", + "rlang", + "vctrs", + "withr" + ], + "Hash": "10d93e97faad6b629301bb3a2fd23378" + }, + "ini": { + "Package": "ini", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6154ec2223172bce8162d4153cda21f7" + }, + "isoband": { + "Package": "isoband", + "Version": "0.2.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grid", + "utils" + ], + "Hash": "0080607b4a1a7b28979aecef976d8bc2" + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools" + ], + "Hash": "5aab57a3bd297eee1c1d862735972182" + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "1.8.8", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods" + ], + "Hash": "e1b9c55281c5adc4dd113652d9e26768" + }, + "knitr": { + "Package": "knitr", + "Version": "1.49", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "evaluate", + "highr", + "methods", + "tools", + "xfun", + "yaml" + ], + "Hash": "9fcb189926d93c636dea94fbe4f44480" + }, + "labeling": { + "Package": "labeling", + "Version": "0.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "graphics", + "stats" + ], + "Hash": "b64ec208ac5bc1852b285f665d6368b3" + }, + "lattice": { + "Package": "lattice", + "Version": "0.22-6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "grid", + "stats", + "utils" + ], + "Hash": "cc5ac1ba4c238c7ca9fa6a87ca11a7e2" + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "1.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "rlang" + ], + "Hash": "b8552d117e1b808b09a832f589b79035" + }, + "lubridate": { + "Package": "lubridate", + "Version": "1.9.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "generics", + "methods", + "timechange" + ], + "Hash": "be38bc740fc51783a78edb5a157e4104" + }, + "magrittr": { + "Package": "magrittr", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "7ce2733a9826b3aeb1775d56fd305472" + }, + "memoise": { + "Package": "memoise", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cachem", + "rlang" + ], + "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c" + }, + "mgcv": { + "Package": "mgcv", + "Version": "1.9-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "Matrix", + "R", + "graphics", + "methods", + "nlme", + "splines", + "stats", + "utils" + ], + "Hash": "110ee9d83b496279960e162ac97764ce" + }, + "mime": { + "Package": "mime", + "Version": "0.12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "tools" + ], + "Hash": "18e9c28c1d3ca1560ce30658b22ce104" + }, + "munsell": { + "Package": "munsell", + "Version": "0.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "colorspace", + "methods" + ], + "Hash": "4fd8900853b746af55b81fda99da7695" + }, + "nlme": { + "Package": "nlme", + "Version": "3.1-166", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "graphics", + "lattice", + "stats", + "utils" + ], + "Hash": "ccbb8846be320b627e6aa2b4616a2ded" + }, + "openssl": { + "Package": "openssl", + "Version": "2.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "askpass" + ], + "Hash": "c62edf62de70cadf40553e10c739049d" + }, + "pillar": { + "Package": "pillar", + "Version": "1.9.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cli", + "fansi", + "glue", + "lifecycle", + "rlang", + "utf8", + "utils", + "vctrs" + ], + "Hash": "15da5a8412f317beeee6175fbc76f4bb" + }, + "pkgconfig": { + "Package": "pkgconfig", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "01f28d4278f15c76cddbea05899c5d6f" + }, + "prettyunits": { + "Package": "prettyunits", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "6b01fc98b1e86c4f705ce9dcfd2f57c7" + }, + "progress": { + "Package": "progress", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "crayon", + "hms", + "prettyunits" + ], + "Hash": "f4625e061cb2865f111b47ff163a5ca6" + }, + "purrr": { + "Package": "purrr", + "Version": "1.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "rlang", + "vctrs" + ], + "Hash": "1cba04a4e9414bdefc9dcaa99649a8dc" + }, + "rappdirs": { + "Package": "rappdirs", + "Version": "0.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5e3c5dc0b071b21fa128676560dbe94d" + }, + "readr": { + "Package": "readr", + "Version": "2.1.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "clipr", + "cpp11", + "crayon", + "hms", + "lifecycle", + "methods", + "rlang", + "tibble", + "tzdb", + "utils", + "vroom" + ], + "Hash": "9de96463d2117f6ac49980577939dfb3" + }, + "remotes": { + "Package": "remotes", + "Version": "2.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods", + "stats", + "tools", + "utils" + ], + "Hash": "3ee025083e66f18db6cf27b56e23e141" + }, + "renv": { + "Package": "renv", + "Version": "1.0.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "397b7b2a265bc5a7a06852524dabae20" + }, + "rlang": { + "Package": "rlang", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "3eec01f8b1dee337674b2e34ab1f9bc1" + }, + "rmarkdown": { + "Package": "rmarkdown", + "Version": "2.29", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bslib", + "evaluate", + "fontawesome", + "htmltools", + "jquerylib", + "jsonlite", + "knitr", + "methods", + "tinytex", + "tools", + "utils", + "xfun", + "yaml" + ], + "Hash": "df99277f63d01c34e95e3d2f06a79736" + }, + "rprojroot": { + "Package": "rprojroot", + "Version": "2.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144" + }, + "sass": { + "Package": "sass", + "Version": "0.4.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "fs", + "htmltools", + "rappdirs", + "rlang" + ], + "Hash": "d53dbfddf695303ea4ad66f86e99b95d" + }, + "scales": { + "Package": "scales", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "RColorBrewer", + "cli", + "farver", + "glue", + "labeling", + "lifecycle", + "munsell", + "rlang", + "viridisLite" + ], + "Hash": "c19df082ba346b0ffa6f833e92de34d1" + }, + "stringi": { + "Package": "stringi", + "Version": "1.8.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "stats", + "tools", + "utils" + ], + "Hash": "39e1144fd75428983dc3f63aa53dfa91" + }, + "stringr": { + "Package": "stringr", + "Version": "1.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "stringi", + "vctrs" + ], + "Hash": "960e2ae9e09656611e0b8214ad543207" + }, + "sys": { + "Package": "sys", + "Version": "3.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "3a1be13d68d47a8cd0bfd74739ca1555" + }, + "tibble": { + "Package": "tibble", + "Version": "3.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "fansi", + "lifecycle", + "magrittr", + "methods", + "pillar", + "pkgconfig", + "rlang", + "utils", + "vctrs" + ], + "Hash": "a84e2cc86d07289b3b6f5069df7a004c" + }, + "tidyselect": { + "Package": "tidyselect", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang", + "vctrs", + "withr" + ], + "Hash": "829f27b9c4919c16b593794a6344d6c0" + }, + "timechange": { + "Package": "timechange", + "Version": "0.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "c5f3c201b931cd6474d17d8700ccb1c8" + }, + "tinytex": { + "Package": "tinytex", + "Version": "0.54", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "xfun" + ], + "Hash": "3ec7e3ddcacc2d34a9046941222bf94d" + }, + "tzdb": { + "Package": "tzdb", + "Version": "0.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "f561504ec2897f4d46f0c7657e488ae1" + }, + "utf8": { + "Package": "utf8", + "Version": "1.2.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "62b65c52671e6665f803ff02954446e9" + }, + "vctrs": { + "Package": "vctrs", + "Version": "0.6.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang" + ], + "Hash": "c03fa420630029418f7e6da3667aac4a" + }, + "viridisLite": { + "Package": "viridisLite", + "Version": "0.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "c826c7c4241b6fc89ff55aaea3fa7491" + }, + "vroom": { + "Package": "vroom", + "Version": "1.6.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bit64", + "cli", + "cpp11", + "crayon", + "glue", + "hms", + "lifecycle", + "methods", + "progress", + "rlang", + "stats", + "tibble", + "tidyselect", + "tzdb", + "vctrs", + "withr" + ], + "Hash": "390f9315bc0025be03012054103d227c" + }, + "withr": { + "Package": "withr", + "Version": "3.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics" + ], + "Hash": "cc2d62c76458d425210d1eb1478b30b4" + }, + "xfun": { + "Package": "xfun", + "Version": "0.49", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "stats", + "tools" + ], + "Hash": "8687398773806cfff9401a2feca96298" + }, + "yaml": { + "Package": "yaml", + "Version": "2.3.10", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "51dab85c6c98e50a18d7551e9d49f76c" + } + } +} diff --git a/renv/.gitignore b/renv/.gitignore new file mode 100644 index 0000000..0ec0cbb --- /dev/null +++ b/renv/.gitignore @@ -0,0 +1,7 @@ +library/ +local/ +cellar/ +lock/ +python/ +sandbox/ +staging/ diff --git a/renv/activate.R b/renv/activate.R new file mode 100644 index 0000000..d13f993 --- /dev/null +++ b/renv/activate.R @@ -0,0 +1,1220 @@ + +local({ + + # the requested version of renv + version <- "1.0.7" + attr(version, "sha") <- NULL + + # the project directory + project <- Sys.getenv("RENV_PROJECT") + if (!nzchar(project)) + project <- getwd() + + # use start-up diagnostics if enabled + diagnostics <- Sys.getenv("RENV_STARTUP_DIAGNOSTICS", unset = "FALSE") + if (diagnostics) { + start <- Sys.time() + profile <- tempfile("renv-startup-", fileext = ".Rprof") + utils::Rprof(profile) + on.exit({ + utils::Rprof(NULL) + elapsed <- signif(difftime(Sys.time(), start, units = "auto"), digits = 2L) + writeLines(sprintf("- renv took %s to run the autoloader.", format(elapsed))) + writeLines(sprintf("- Profile: %s", profile)) + print(utils::summaryRprof(profile)) + }, add = TRUE) + } + + # figure out whether the autoloader is enabled + enabled <- local({ + + # first, check config option + override <- getOption("renv.config.autoloader.enabled") + if (!is.null(override)) + return(override) + + # if we're being run in a context where R_LIBS is already set, + # don't load -- presumably we're being run as a sub-process and + # the parent process has already set up library paths for us + rcmd <- Sys.getenv("R_CMD", unset = NA) + rlibs <- Sys.getenv("R_LIBS", unset = NA) + if (!is.na(rlibs) && !is.na(rcmd)) + return(FALSE) + + # next, check environment variables + # TODO: prefer using the configuration one in the future + envvars <- c( + "RENV_CONFIG_AUTOLOADER_ENABLED", + "RENV_AUTOLOADER_ENABLED", + "RENV_ACTIVATE_PROJECT" + ) + + for (envvar in envvars) { + envval <- Sys.getenv(envvar, unset = NA) + if (!is.na(envval)) + return(tolower(envval) %in% c("true", "t", "1")) + } + + # enable by default + TRUE + + }) + + # bail if we're not enabled + if (!enabled) { + + # if we're not enabled, we might still need to manually load + # the user profile here + profile <- Sys.getenv("R_PROFILE_USER", unset = "~/.Rprofile") + if (file.exists(profile)) { + cfg <- Sys.getenv("RENV_CONFIG_USER_PROFILE", unset = "TRUE") + if (tolower(cfg) %in% c("true", "t", "1")) + sys.source(profile, envir = globalenv()) + } + + return(FALSE) + + } + + # avoid recursion + if (identical(getOption("renv.autoloader.running"), TRUE)) { + warning("ignoring recursive attempt to run renv autoloader") + return(invisible(TRUE)) + } + + # signal that we're loading renv during R startup + options(renv.autoloader.running = TRUE) + on.exit(options(renv.autoloader.running = NULL), add = TRUE) + + # signal that we've consented to use renv + options(renv.consent = TRUE) + + # load the 'utils' package eagerly -- this ensures that renv shims, which + # mask 'utils' packages, will come first on the search path + library(utils, lib.loc = .Library) + + # unload renv if it's already been loaded + if ("renv" %in% loadedNamespaces()) + unloadNamespace("renv") + + # load bootstrap tools + `%||%` <- function(x, y) { + if (is.null(x)) y else x + } + + catf <- function(fmt, ..., appendLF = TRUE) { + + quiet <- getOption("renv.bootstrap.quiet", default = FALSE) + if (quiet) + return(invisible()) + + msg <- sprintf(fmt, ...) + cat(msg, file = stdout(), sep = if (appendLF) "\n" else "") + + invisible(msg) + + } + + header <- function(label, + ..., + prefix = "#", + suffix = "-", + n = min(getOption("width"), 78)) + { + label <- sprintf(label, ...) + n <- max(n - nchar(label) - nchar(prefix) - 2L, 8L) + if (n <= 0) + return(paste(prefix, label)) + + tail <- paste(rep.int(suffix, n), collapse = "") + paste0(prefix, " ", label, " ", tail) + + } + + heredoc <- function(text, leave = 0) { + + # remove leading, trailing whitespace + trimmed <- gsub("^\\s*\\n|\\n\\s*$", "", text) + + # split into lines + lines <- strsplit(trimmed, "\n", fixed = TRUE)[[1L]] + + # compute common indent + indent <- regexpr("[^[:space:]]", lines) + common <- min(setdiff(indent, -1L)) - leave + paste(substring(lines, common), collapse = "\n") + + } + + startswith <- function(string, prefix) { + substring(string, 1, nchar(prefix)) == prefix + } + + bootstrap <- function(version, library) { + + friendly <- renv_bootstrap_version_friendly(version) + section <- header(sprintf("Bootstrapping renv %s", friendly)) + catf(section) + + # attempt to download renv + catf("- Downloading renv ... ", appendLF = FALSE) + withCallingHandlers( + tarball <- renv_bootstrap_download(version), + error = function(err) { + catf("FAILED") + stop("failed to download:\n", conditionMessage(err)) + } + ) + catf("OK") + on.exit(unlink(tarball), add = TRUE) + + # now attempt to install + catf("- Installing renv ... ", appendLF = FALSE) + withCallingHandlers( + status <- renv_bootstrap_install(version, tarball, library), + error = function(err) { + catf("FAILED") + stop("failed to install:\n", conditionMessage(err)) + } + ) + catf("OK") + + # add empty line to break up bootstrapping from normal output + catf("") + + return(invisible()) + } + + renv_bootstrap_tests_running <- function() { + getOption("renv.tests.running", default = FALSE) + } + + renv_bootstrap_repos <- function() { + + # get CRAN repository + cran <- getOption("renv.repos.cran", "https://cloud.r-project.org") + + # check for repos override + repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) + if (!is.na(repos)) { + + # check for RSPM; if set, use a fallback repository for renv + rspm <- Sys.getenv("RSPM", unset = NA) + if (identical(rspm, repos)) + repos <- c(RSPM = rspm, CRAN = cran) + + return(repos) + + } + + # check for lockfile repositories + repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity) + if (!inherits(repos, "error") && length(repos)) + return(repos) + + # retrieve current repos + repos <- getOption("repos") + + # ensure @CRAN@ entries are resolved + repos[repos == "@CRAN@"] <- cran + + # add in renv.bootstrap.repos if set + default <- c(FALLBACK = "https://cloud.r-project.org") + extra <- getOption("renv.bootstrap.repos", default = default) + repos <- c(repos, extra) + + # remove duplicates that might've snuck in + dupes <- duplicated(repos) | duplicated(names(repos)) + repos[!dupes] + + } + + renv_bootstrap_repos_lockfile <- function() { + + lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock") + if (!file.exists(lockpath)) + return(NULL) + + lockfile <- tryCatch(renv_json_read(lockpath), error = identity) + if (inherits(lockfile, "error")) { + warning(lockfile) + return(NULL) + } + + repos <- lockfile$R$Repositories + if (length(repos) == 0) + return(NULL) + + keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1)) + vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1)) + names(vals) <- keys + + return(vals) + + } + + renv_bootstrap_download <- function(version) { + + sha <- attr(version, "sha", exact = TRUE) + + methods <- if (!is.null(sha)) { + + # attempting to bootstrap a development version of renv + c( + function() renv_bootstrap_download_tarball(sha), + function() renv_bootstrap_download_github(sha) + ) + + } else { + + # attempting to bootstrap a release version of renv + c( + function() renv_bootstrap_download_tarball(version), + function() renv_bootstrap_download_cran_latest(version), + function() renv_bootstrap_download_cran_archive(version) + ) + + } + + for (method in methods) { + path <- tryCatch(method(), error = identity) + if (is.character(path) && file.exists(path)) + return(path) + } + + stop("All download methods failed") + + } + + renv_bootstrap_download_impl <- function(url, destfile) { + + mode <- "wb" + + # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 + fixup <- + Sys.info()[["sysname"]] == "Windows" && + substring(url, 1L, 5L) == "file:" + + if (fixup) + mode <- "w+b" + + args <- list( + url = url, + destfile = destfile, + mode = mode, + quiet = TRUE + ) + + if ("headers" %in% names(formals(utils::download.file))) + args$headers <- renv_bootstrap_download_custom_headers(url) + + do.call(utils::download.file, args) + + } + + renv_bootstrap_download_custom_headers <- function(url) { + + headers <- getOption("renv.download.headers") + if (is.null(headers)) + return(character()) + + if (!is.function(headers)) + stopf("'renv.download.headers' is not a function") + + headers <- headers(url) + if (length(headers) == 0L) + return(character()) + + if (is.list(headers)) + headers <- unlist(headers, recursive = FALSE, use.names = TRUE) + + ok <- + is.character(headers) && + is.character(names(headers)) && + all(nzchar(names(headers))) + + if (!ok) + stop("invocation of 'renv.download.headers' did not return a named character vector") + + headers + + } + + renv_bootstrap_download_cran_latest <- function(version) { + + spec <- renv_bootstrap_download_cran_latest_find(version) + type <- spec$type + repos <- spec$repos + + baseurl <- utils::contrib.url(repos = repos, type = type) + ext <- if (identical(type, "source")) + ".tar.gz" + else if (Sys.info()[["sysname"]] == "Windows") + ".zip" + else + ".tgz" + name <- sprintf("renv_%s%s", version, ext) + url <- paste(baseurl, name, sep = "/") + + destfile <- file.path(tempdir(), name) + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (inherits(status, "condition")) + return(FALSE) + + # report success and return + destfile + + } + + renv_bootstrap_download_cran_latest_find <- function(version) { + + # check whether binaries are supported on this system + binary <- + getOption("renv.bootstrap.binary", default = TRUE) && + !identical(.Platform$pkgType, "source") && + !identical(getOption("pkgType"), "source") && + Sys.info()[["sysname"]] %in% c("Darwin", "Windows") + + types <- c(if (binary) "binary", "source") + + # iterate over types + repositories + for (type in types) { + for (repos in renv_bootstrap_repos()) { + + # retrieve package database + db <- tryCatch( + as.data.frame( + utils::available.packages(type = type, repos = repos), + stringsAsFactors = FALSE + ), + error = identity + ) + + if (inherits(db, "error")) + next + + # check for compatible entry + entry <- db[db$Package %in% "renv" & db$Version %in% version, ] + if (nrow(entry) == 0) + next + + # found it; return spec to caller + spec <- list(entry = entry, type = type, repos = repos) + return(spec) + + } + } + + # if we got here, we failed to find renv + fmt <- "renv %s is not available from your declared package repositories" + stop(sprintf(fmt, version)) + + } + + renv_bootstrap_download_cran_archive <- function(version) { + + name <- sprintf("renv_%s.tar.gz", version) + repos <- renv_bootstrap_repos() + urls <- file.path(repos, "src/contrib/Archive/renv", name) + destfile <- file.path(tempdir(), name) + + for (url in urls) { + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (identical(status, 0L)) + return(destfile) + + } + + return(FALSE) + + } + + renv_bootstrap_download_tarball <- function(version) { + + # if the user has provided the path to a tarball via + # an environment variable, then use it + tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA) + if (is.na(tarball)) + return() + + # allow directories + if (dir.exists(tarball)) { + name <- sprintf("renv_%s.tar.gz", version) + tarball <- file.path(tarball, name) + } + + # bail if it doesn't exist + if (!file.exists(tarball)) { + + # let the user know we weren't able to honour their request + fmt <- "- RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist." + msg <- sprintf(fmt, tarball) + warning(msg) + + # bail + return() + + } + + catf("- Using local tarball '%s'.", tarball) + tarball + + } + + renv_bootstrap_download_github <- function(version) { + + enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") + if (!identical(enabled, "TRUE")) + return(FALSE) + + # prepare download options + pat <- Sys.getenv("GITHUB_PAT") + if (nzchar(Sys.which("curl")) && nzchar(pat)) { + fmt <- "--location --fail --header \"Authorization: token %s\"" + extra <- sprintf(fmt, pat) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "curl", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } else if (nzchar(Sys.which("wget")) && nzchar(pat)) { + fmt <- "--header=\"Authorization: token %s\"" + extra <- sprintf(fmt, pat) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "wget", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } + + url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) + name <- sprintf("renv_%s.tar.gz", version) + destfile <- file.path(tempdir(), name) + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (!identical(status, 0L)) + return(FALSE) + + renv_bootstrap_download_augment(destfile) + + return(destfile) + + } + + # Add Sha to DESCRIPTION. This is stop gap until #890, after which we + # can use renv::install() to fully capture metadata. + renv_bootstrap_download_augment <- function(destfile) { + sha <- renv_bootstrap_git_extract_sha1_tar(destfile) + if (is.null(sha)) { + return() + } + + # Untar + tempdir <- tempfile("renv-github-") + on.exit(unlink(tempdir, recursive = TRUE), add = TRUE) + untar(destfile, exdir = tempdir) + pkgdir <- dir(tempdir, full.names = TRUE)[[1]] + + # Modify description + desc_path <- file.path(pkgdir, "DESCRIPTION") + desc_lines <- readLines(desc_path) + remotes_fields <- c( + "RemoteType: github", + "RemoteHost: api.github.com", + "RemoteRepo: renv", + "RemoteUsername: rstudio", + "RemotePkgRef: rstudio/renv", + paste("RemoteRef: ", sha), + paste("RemoteSha: ", sha) + ) + writeLines(c(desc_lines[desc_lines != ""], remotes_fields), con = desc_path) + + # Re-tar + local({ + old <- setwd(tempdir) + on.exit(setwd(old), add = TRUE) + + tar(destfile, compression = "gzip") + }) + invisible() + } + + # Extract the commit hash from a git archive. Git archives include the SHA1 + # hash as the comment field of the tarball pax extended header + # (see https://www.kernel.org/pub/software/scm/git/docs/git-archive.html) + # For GitHub archives this should be the first header after the default one + # (512 byte) header. + renv_bootstrap_git_extract_sha1_tar <- function(bundle) { + + # open the bundle for reading + # We use gzcon for everything because (from ?gzcon) + # > Reading from a connection which does not supply a 'gzip' magic + # > header is equivalent to reading from the original connection + conn <- gzcon(file(bundle, open = "rb", raw = TRUE)) + on.exit(close(conn)) + + # The default pax header is 512 bytes long and the first pax extended header + # with the comment should be 51 bytes long + # `52 comment=` (11 chars) + 40 byte SHA1 hash + len <- 0x200 + 0x33 + res <- rawToChar(readBin(conn, "raw", n = len)[0x201:len]) + + if (grepl("^52 comment=", res)) { + sub("52 comment=", "", res) + } else { + NULL + } + } + + renv_bootstrap_install <- function(version, tarball, library) { + + # attempt to install it into project library + dir.create(library, showWarnings = FALSE, recursive = TRUE) + output <- renv_bootstrap_install_impl(library, tarball) + + # check for successful install + status <- attr(output, "status") + if (is.null(status) || identical(status, 0L)) + return(status) + + # an error occurred; report it + header <- "installation of renv failed" + lines <- paste(rep.int("=", nchar(header)), collapse = "") + text <- paste(c(header, lines, output), collapse = "\n") + stop(text) + + } + + renv_bootstrap_install_impl <- function(library, tarball) { + + # invoke using system2 so we can capture and report output + bin <- R.home("bin") + exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" + R <- file.path(bin, exe) + + args <- c( + "--vanilla", "CMD", "INSTALL", "--no-multiarch", + "-l", shQuote(path.expand(library)), + shQuote(path.expand(tarball)) + ) + + system2(R, args, stdout = TRUE, stderr = TRUE) + + } + + renv_bootstrap_platform_prefix <- function() { + + # construct version prefix + version <- paste(R.version$major, R.version$minor, sep = ".") + prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-") + + # include SVN revision for development versions of R + # (to avoid sharing platform-specific artefacts with released versions of R) + devel <- + identical(R.version[["status"]], "Under development (unstable)") || + identical(R.version[["nickname"]], "Unsuffered Consequences") + + if (devel) + prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r") + + # build list of path components + components <- c(prefix, R.version$platform) + + # include prefix if provided by user + prefix <- renv_bootstrap_platform_prefix_impl() + if (!is.na(prefix) && nzchar(prefix)) + components <- c(prefix, components) + + # build prefix + paste(components, collapse = "/") + + } + + renv_bootstrap_platform_prefix_impl <- function() { + + # if an explicit prefix has been supplied, use it + prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) + if (!is.na(prefix)) + return(prefix) + + # if the user has requested an automatic prefix, generate it + auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) + if (is.na(auto) && getRversion() >= "4.4.0") + auto <- "TRUE" + + if (auto %in% c("TRUE", "True", "true", "1")) + return(renv_bootstrap_platform_prefix_auto()) + + # empty string on failure + "" + + } + + renv_bootstrap_platform_prefix_auto <- function() { + + prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) + if (inherits(prefix, "error") || prefix %in% "unknown") { + + msg <- paste( + "failed to infer current operating system", + "please file a bug report at https://github.com/rstudio/renv/issues", + sep = "; " + ) + + warning(msg) + + } + + prefix + + } + + renv_bootstrap_platform_os <- function() { + + sysinfo <- Sys.info() + sysname <- sysinfo[["sysname"]] + + # handle Windows + macOS up front + if (sysname == "Windows") + return("windows") + else if (sysname == "Darwin") + return("macos") + + # check for os-release files + for (file in c("/etc/os-release", "/usr/lib/os-release")) + if (file.exists(file)) + return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) + + # check for redhat-release files + if (file.exists("/etc/redhat-release")) + return(renv_bootstrap_platform_os_via_redhat_release()) + + "unknown" + + } + + renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { + + # read /etc/os-release + release <- utils::read.table( + file = file, + sep = "=", + quote = c("\"", "'"), + col.names = c("Key", "Value"), + comment.char = "#", + stringsAsFactors = FALSE + ) + + vars <- as.list(release$Value) + names(vars) <- release$Key + + # get os name + os <- tolower(sysinfo[["sysname"]]) + + # read id + id <- "unknown" + for (field in c("ID", "ID_LIKE")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + id <- vars[[field]] + break + } + } + + # read version + version <- "unknown" + for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + version <- vars[[field]] + break + } + } + + # join together + paste(c(os, id, version), collapse = "-") + + } + + renv_bootstrap_platform_os_via_redhat_release <- function() { + + # read /etc/redhat-release + contents <- readLines("/etc/redhat-release", warn = FALSE) + + # infer id + id <- if (grepl("centos", contents, ignore.case = TRUE)) + "centos" + else if (grepl("redhat", contents, ignore.case = TRUE)) + "redhat" + else + "unknown" + + # try to find a version component (very hacky) + version <- "unknown" + + parts <- strsplit(contents, "[[:space:]]")[[1L]] + for (part in parts) { + + nv <- tryCatch(numeric_version(part), error = identity) + if (inherits(nv, "error")) + next + + version <- nv[1, 1] + break + + } + + paste(c("linux", id, version), collapse = "-") + + } + + renv_bootstrap_library_root_name <- function(project) { + + # use project name as-is if requested + asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE") + if (asis) + return(basename(project)) + + # otherwise, disambiguate based on project's path + id <- substring(renv_bootstrap_hash_text(project), 1L, 8L) + paste(basename(project), id, sep = "-") + + } + + renv_bootstrap_library_root <- function(project) { + + prefix <- renv_bootstrap_profile_prefix() + + path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) + if (!is.na(path)) + return(paste(c(path, prefix), collapse = "/")) + + path <- renv_bootstrap_library_root_impl(project) + if (!is.null(path)) { + name <- renv_bootstrap_library_root_name(project) + return(paste(c(path, prefix, name), collapse = "/")) + } + + renv_bootstrap_paths_renv("library", project = project) + + } + + renv_bootstrap_library_root_impl <- function(project) { + + root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) + if (!is.na(root)) + return(root) + + type <- renv_bootstrap_project_type(project) + if (identical(type, "package")) { + userdir <- renv_bootstrap_user_dir() + return(file.path(userdir, "library")) + } + + } + + renv_bootstrap_validate_version <- function(version, description = NULL) { + + # resolve description file + # + # avoid passing lib.loc to `packageDescription()` below, since R will + # use the loaded version of the package by default anyhow. note that + # this function should only be called after 'renv' is loaded + # https://github.com/rstudio/renv/issues/1625 + description <- description %||% packageDescription("renv") + + # check whether requested version 'version' matches loaded version of renv + sha <- attr(version, "sha", exact = TRUE) + valid <- if (!is.null(sha)) + renv_bootstrap_validate_version_dev(sha, description) + else + renv_bootstrap_validate_version_release(version, description) + + if (valid) + return(TRUE) + + # the loaded version of renv doesn't match the requested version; + # give the user instructions on how to proceed + dev <- identical(description[["RemoteType"]], "github") + remote <- if (dev) + paste("rstudio/renv", description[["RemoteSha"]], sep = "@") + else + paste("renv", description[["Version"]], sep = "@") + + # display both loaded version + sha if available + friendly <- renv_bootstrap_version_friendly( + version = description[["Version"]], + sha = if (dev) description[["RemoteSha"]] + ) + + fmt <- heredoc(" + renv %1$s was loaded from project library, but this project is configured to use renv %2$s. + - Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile. + - Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library. + ") + catf(fmt, friendly, renv_bootstrap_version_friendly(version), remote) + + FALSE + + } + + renv_bootstrap_validate_version_dev <- function(version, description) { + expected <- description[["RemoteSha"]] + is.character(expected) && startswith(expected, version) + } + + renv_bootstrap_validate_version_release <- function(version, description) { + expected <- description[["Version"]] + is.character(expected) && identical(expected, version) + } + + renv_bootstrap_hash_text <- function(text) { + + hashfile <- tempfile("renv-hash-") + on.exit(unlink(hashfile), add = TRUE) + + writeLines(text, con = hashfile) + tools::md5sum(hashfile) + + } + + renv_bootstrap_load <- function(project, libpath, version) { + + # try to load renv from the project library + if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) + return(FALSE) + + # warn if the version of renv loaded does not match + renv_bootstrap_validate_version(version) + + # execute renv load hooks, if any + hooks <- getHook("renv::autoload") + for (hook in hooks) + if (is.function(hook)) + tryCatch(hook(), error = warnify) + + # load the project + renv::load(project) + + TRUE + + } + + renv_bootstrap_profile_load <- function(project) { + + # if RENV_PROFILE is already set, just use that + profile <- Sys.getenv("RENV_PROFILE", unset = NA) + if (!is.na(profile) && nzchar(profile)) + return(profile) + + # check for a profile file (nothing to do if it doesn't exist) + path <- renv_bootstrap_paths_renv("profile", profile = FALSE, project = project) + if (!file.exists(path)) + return(NULL) + + # read the profile, and set it if it exists + contents <- readLines(path, warn = FALSE) + if (length(contents) == 0L) + return(NULL) + + # set RENV_PROFILE + profile <- contents[[1L]] + if (!profile %in% c("", "default")) + Sys.setenv(RENV_PROFILE = profile) + + profile + + } + + renv_bootstrap_profile_prefix <- function() { + profile <- renv_bootstrap_profile_get() + if (!is.null(profile)) + return(file.path("profiles", profile, "renv")) + } + + renv_bootstrap_profile_get <- function() { + profile <- Sys.getenv("RENV_PROFILE", unset = "") + renv_bootstrap_profile_normalize(profile) + } + + renv_bootstrap_profile_set <- function(profile) { + profile <- renv_bootstrap_profile_normalize(profile) + if (is.null(profile)) + Sys.unsetenv("RENV_PROFILE") + else + Sys.setenv(RENV_PROFILE = profile) + } + + renv_bootstrap_profile_normalize <- function(profile) { + + if (is.null(profile) || profile %in% c("", "default")) + return(NULL) + + profile + + } + + renv_bootstrap_path_absolute <- function(path) { + + substr(path, 1L, 1L) %in% c("~", "/", "\\") || ( + substr(path, 1L, 1L) %in% c(letters, LETTERS) && + substr(path, 2L, 3L) %in% c(":/", ":\\") + ) + + } + + renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) { + renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv") + root <- if (renv_bootstrap_path_absolute(renv)) NULL else project + prefix <- if (profile) renv_bootstrap_profile_prefix() + components <- c(root, renv, prefix, ...) + paste(components, collapse = "/") + } + + renv_bootstrap_project_type <- function(path) { + + descpath <- file.path(path, "DESCRIPTION") + if (!file.exists(descpath)) + return("unknown") + + desc <- tryCatch( + read.dcf(descpath, all = TRUE), + error = identity + ) + + if (inherits(desc, "error")) + return("unknown") + + type <- desc$Type + if (!is.null(type)) + return(tolower(type)) + + package <- desc$Package + if (!is.null(package)) + return("package") + + "unknown" + + } + + renv_bootstrap_user_dir <- function() { + dir <- renv_bootstrap_user_dir_impl() + path.expand(chartr("\\", "/", dir)) + } + + renv_bootstrap_user_dir_impl <- function() { + + # use local override if set + override <- getOption("renv.userdir.override") + if (!is.null(override)) + return(override) + + # use R_user_dir if available + tools <- asNamespace("tools") + if (is.function(tools$R_user_dir)) + return(tools$R_user_dir("renv", "cache")) + + # try using our own backfill for older versions of R + envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME") + for (envvar in envvars) { + root <- Sys.getenv(envvar, unset = NA) + if (!is.na(root)) + return(file.path(root, "R/renv")) + } + + # use platform-specific default fallbacks + if (Sys.info()[["sysname"]] == "Windows") + file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv") + else if (Sys.info()[["sysname"]] == "Darwin") + "~/Library/Caches/org.R-project.R/R/renv" + else + "~/.cache/R/renv" + + } + + renv_bootstrap_version_friendly <- function(version, shafmt = NULL, sha = NULL) { + sha <- sha %||% attr(version, "sha", exact = TRUE) + parts <- c(version, sprintf(shafmt %||% " [sha: %s]", substring(sha, 1L, 7L))) + paste(parts, collapse = "") + } + + renv_bootstrap_exec <- function(project, libpath, version) { + if (!renv_bootstrap_load(project, libpath, version)) + renv_bootstrap_run(version, libpath) + } + + renv_bootstrap_run <- function(version, libpath) { + + # perform bootstrap + bootstrap(version, libpath) + + # exit early if we're just testing bootstrap + if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) + return(TRUE) + + # try again to load + if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { + return(renv::load(project = getwd())) + } + + # failed to download or load renv; warn the user + msg <- c( + "Failed to find an renv installation: the project will not be loaded.", + "Use `renv::activate()` to re-initialize the project." + ) + + warning(paste(msg, collapse = "\n"), call. = FALSE) + + } + + renv_json_read <- function(file = NULL, text = NULL) { + + jlerr <- NULL + + # if jsonlite is loaded, use that instead + if ("jsonlite" %in% loadedNamespaces()) { + + json <- tryCatch(renv_json_read_jsonlite(file, text), error = identity) + if (!inherits(json, "error")) + return(json) + + jlerr <- json + + } + + # otherwise, fall back to the default JSON reader + json <- tryCatch(renv_json_read_default(file, text), error = identity) + if (!inherits(json, "error")) + return(json) + + # report an error + if (!is.null(jlerr)) + stop(jlerr) + else + stop(json) + + } + + renv_json_read_jsonlite <- function(file = NULL, text = NULL) { + text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") + jsonlite::fromJSON(txt = text, simplifyVector = FALSE) + } + + renv_json_read_default <- function(file = NULL, text = NULL) { + + # find strings in the JSON + text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") + pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + locs <- gregexpr(pattern, text, perl = TRUE)[[1]] + + # if any are found, replace them with placeholders + replaced <- text + strings <- character() + replacements <- character() + + if (!identical(c(locs), -1L)) { + + # get the string values + starts <- locs + ends <- locs + attr(locs, "match.length") - 1L + strings <- substring(text, starts, ends) + + # only keep those requiring escaping + strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE) + + # compute replacements + replacements <- sprintf('"\032%i\032"', seq_along(strings)) + + # replace the strings + mapply(function(string, replacement) { + replaced <<- sub(string, replacement, replaced, fixed = TRUE) + }, strings, replacements) + + } + + # transform the JSON into something the R parser understands + transformed <- replaced + transformed <- gsub("{}", "`names<-`(list(), character())", transformed, fixed = TRUE) + transformed <- gsub("[[{]", "list(", transformed, perl = TRUE) + transformed <- gsub("[]}]", ")", transformed, perl = TRUE) + transformed <- gsub(":", "=", transformed, fixed = TRUE) + text <- paste(transformed, collapse = "\n") + + # parse it + json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]] + + # construct map between source strings, replaced strings + map <- as.character(parse(text = strings)) + names(map) <- as.character(parse(text = replacements)) + + # convert to list + map <- as.list(map) + + # remap strings in object + remapped <- renv_json_read_remap(json, map) + + # evaluate + eval(remapped, envir = baseenv()) + + } + + renv_json_read_remap <- function(json, map) { + + # fix names + if (!is.null(names(json))) { + lhs <- match(names(json), names(map), nomatch = 0L) + rhs <- match(names(map), names(json), nomatch = 0L) + names(json)[rhs] <- map[lhs] + } + + # fix values + if (is.character(json)) + return(map[[json]] %||% json) + + # handle true, false, null + if (is.name(json)) { + text <- as.character(json) + if (text == "true") + return(TRUE) + else if (text == "false") + return(FALSE) + else if (text == "null") + return(NULL) + } + + # recurse + if (is.recursive(json)) { + for (i in seq_along(json)) { + json[i] <- list(renv_json_read_remap(json[[i]], map)) + } + } + + json + + } + + # load the renv profile, if any + renv_bootstrap_profile_load(project) + + # construct path to library root + root <- renv_bootstrap_library_root(project) + + # construct library prefix for platform + prefix <- renv_bootstrap_platform_prefix() + + # construct full libpath + libpath <- file.path(root, prefix) + + # run bootstrap code + renv_bootstrap_exec(project, libpath, version) + + invisible() + +}) diff --git a/renv/settings.json b/renv/settings.json new file mode 100644 index 0000000..ffdbb32 --- /dev/null +++ b/renv/settings.json @@ -0,0 +1,19 @@ +{ + "bioconductor.version": null, + "external.libraries": [], + "ignored.packages": [], + "package.dependency.fields": [ + "Imports", + "Depends", + "LinkingTo" + ], + "ppm.enabled": null, + "ppm.ignored.urls": [], + "r.version": null, + "snapshot.type": "implicit", + "use.cache": true, + "vcs.ignore.cellar": true, + "vcs.ignore.library": true, + "vcs.ignore.local": true, + "vcs.manage.ignores": true +} From fd3fb0024ba7c1fb881a6e9513af2e948b2fa9db Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:47:37 +0000 Subject: [PATCH 08/25] Add renv --- .github/workflows/knit-rmd.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index 8af95ce..07de36b 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -24,9 +24,8 @@ jobs: - name: Set up R uses: r-lib/actions/setup-r@v2 - - name: Install dependencies - run: | - Rscript -e 'install.packages(c("rmarkdown", "knitr")); remotes::install_github("SAFEHR-data/omopcept")' + - name: Setup Renv + uses: r-lib/actions/setup-renv@v2 - name: Find and knit Rmd files run: | From f4c55d2e887ca71f96992705324230db4f1372de Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:51:26 +0000 Subject: [PATCH 09/25] Add omopcept --- .github/workflows/knit-rmd.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index 07de36b..2dd5fe8 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -27,6 +27,13 @@ jobs: - name: Setup Renv uses: r-lib/actions/setup-renv@v2 + - name: Tmp install omopcept in rmd # doesnt install on local because of arrow error + run: | + Rscript -e ' + remotes::install_github("SAFEHR-data/omopcept") + renv::snapshot() + ' + - name: Find and knit Rmd files run: | Rscript -e ' From 3c5fcc50db2f5b26515191dd1e10f3a306b7987c Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 16:59:55 +0000 Subject: [PATCH 10/25] Add token to read omopcept --- .github/workflows/knit-rmd.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index 2dd5fe8..ac606b2 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -33,6 +33,8 @@ jobs: remotes::install_github("SAFEHR-data/omopcept") renv::snapshot() ' + env: + GITHUB_PAT: ${{ secrets.READ_OMOPCEPT_PAT }} - name: Find and knit Rmd files run: | From e7ce62bc9ef8ab3501c13f3530cf51962304a051 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 17:03:38 +0000 Subject: [PATCH 11/25] Hopefully add omopcept and commit --- .github/workflows/knit-rmd.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index ac606b2..d568292 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -26,6 +26,8 @@ jobs: - name: Setup Renv uses: r-lib/actions/setup-renv@v2 + env: + GITHUB_PAT: ${{ secrets.READ_OMOPCEPT_PAT }} - name: Tmp install omopcept in rmd # doesnt install on local because of arrow error run: | @@ -36,6 +38,19 @@ jobs: env: GITHUB_PAT: ${{ secrets.READ_OMOPCEPT_PAT }} + + - name: Tmp commit changes + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m "Add omopcept" || echo "No changes to commit" + + - name: Push changes + uses: ad-m/github-push-action@v0.8.0 + with: + branch: ${{ github.head_ref }} + - name: Find and knit Rmd files run: | Rscript -e ' From 5b48afbb5d3156d634a660490ab387e8a6da045d Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 17:13:25 +0000 Subject: [PATCH 12/25] This is getting silly now --- .github/workflows/knit-rmd.yaml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index d568292..8a575ba 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -39,17 +39,13 @@ jobs: GITHUB_PAT: ${{ secrets.READ_OMOPCEPT_PAT }} - - name: Tmp commit changes + - name: Show changes run: | git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" git add -A git commit -m "Add omopcept" || echo "No changes to commit" - - - name: Push changes - uses: ad-m/github-push-action@v0.8.0 - with: - branch: ${{ github.head_ref }} + git format-patch -1 HEAD - name: Find and knit Rmd files run: | @@ -70,4 +66,4 @@ jobs: - name: Push changes uses: ad-m/github-push-action@v0.8.0 with: - branch: ${{ github.head_ref }} + branch: ${{ github.head_ref || github.ref_name }} From ab4faac08b729b4fe20c63d035ecfee1260ab072 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 17:16:42 +0000 Subject: [PATCH 13/25] Only pull current branch --- .github/workflows/knit-rmd.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index 8a575ba..d7e2f68 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -20,6 +20,10 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + # Only pull current branch, not the merge outcome so that we can commit the output + with: + ref: ${{ github.head_ref || github.ref_name }} + fetch-depth: 0 - name: Set up R uses: r-lib/actions/setup-r@v2 From 10ca4ea1a71977d0b9c58ae03abc3be8fac3f3da Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 17:17:42 +0000 Subject: [PATCH 14/25] Try and push changes now Fallback to showing patch --- .github/workflows/knit-rmd.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index d7e2f68..a17a09f 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -50,6 +50,12 @@ jobs: git add -A git commit -m "Add omopcept" || echo "No changes to commit" git format-patch -1 HEAD + cat 0001-Add-omopcept.patch + + - name: Push changes + uses: ad-m/github-push-action@v0.8.0 + with: + branch: ${{ github.head_ref || github.ref_name }} - name: Find and knit Rmd files run: | From f2fbef66b9ffa9873677d9e0c73ded6c07130669 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Dec 2024 17:19:59 +0000 Subject: [PATCH 15/25] Add omopcept --- renv.lock | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/renv.lock b/renv.lock index e67dc3a..c11536b 100644 --- a/renv.lock +++ b/renv.lock @@ -61,6 +61,28 @@ ], "Hash": "45f0398006e83a5b10b72a90663d8d8c" }, + "arrow": { + "Package": "arrow", + "Version": "18.1.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "R6", + "assertthat", + "bit64", + "cpp11", + "glue", + "methods", + "purrr", + "rlang", + "stats", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "d83c5ed8c1a89c5fd5788a8da714364e" + }, "askpass": { "Package": "askpass", "Version": "1.2.0", @@ -71,6 +93,16 @@ ], "Hash": "cad6cf7f1d5f6e906700b9d3e718c796" }, + "assertthat": { + "Package": "assertthat", + "Version": "0.2.1", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "tools" + ], + "Hash": "50c838a310445e954bc13f26f26a6ecf" + }, "base64enc": { "Package": "base64enc", "Version": "0.1-3", @@ -640,6 +672,28 @@ ], "Hash": "ccbb8846be320b627e6aa2b4616a2ded" }, + "omopcept": { + "Package": "omopcept", + "Version": "0.0.6.1", + "Source": "GitHub", + "RemoteType": "github", + "RemoteHost": "api.github.com", + "RemoteRepo": "omopcept", + "RemoteUsername": "SAFEHR-data", + "RemoteRef": "HEAD", + "RemoteSha": "145c5e82c2f252903dbb5ca52f50a0d841ed09b2", + "Requirements": [ + "R", + "arrow", + "dplyr", + "ggplot2", + "lubridate", + "readr", + "rlang", + "stringr" + ], + "Hash": "046e0eba1d9ac70bd15bab91577e19a9" + }, "openssl": { "Package": "openssl", "Version": "2.2.1", @@ -652,12 +706,11 @@ }, "pillar": { "Package": "pillar", - "Version": "1.9.0", + "Version": "1.10.0", "Source": "Repository", - "Repository": "CRAN", + "Repository": "RSPM", "Requirements": [ "cli", - "fansi", "glue", "lifecycle", "rlang", @@ -665,7 +718,7 @@ "utils", "vctrs" ], - "Hash": "15da5a8412f317beeee6175fbc76f4bb" + "Hash": "101ca350beea21261a15ba169d7a8513" }, "pkgconfig": { "Package": "pkgconfig", From 7ef7656e41b65722615ef84992a3b6c17a136d33 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 17:21:13 +0000 Subject: [PATCH 16/25] Remove extra install of omopcept --- .github/workflows/knit-rmd.yaml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index a17a09f..8946f18 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -42,21 +42,6 @@ jobs: env: GITHUB_PAT: ${{ secrets.READ_OMOPCEPT_PAT }} - - - name: Show changes - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git add -A - git commit -m "Add omopcept" || echo "No changes to commit" - git format-patch -1 HEAD - cat 0001-Add-omopcept.patch - - - name: Push changes - uses: ad-m/github-push-action@v0.8.0 - with: - branch: ${{ github.head_ref || github.ref_name }} - - name: Find and knit Rmd files run: | Rscript -e ' From d4080240e979eedce5c94480e7654e06edc9828a Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 23 Dec 2024 17:33:13 +0000 Subject: [PATCH 17/25] Remove installing of omopcept on its own --- .github/workflows/knit-rmd.yaml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index 8946f18..74cc1fa 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -33,15 +33,6 @@ jobs: env: GITHUB_PAT: ${{ secrets.READ_OMOPCEPT_PAT }} - - name: Tmp install omopcept in rmd # doesnt install on local because of arrow error - run: | - Rscript -e ' - remotes::install_github("SAFEHR-data/omopcept") - renv::snapshot() - ' - env: - GITHUB_PAT: ${{ secrets.READ_OMOPCEPT_PAT }} - - name: Find and knit Rmd files run: | Rscript -e ' From 3336e8ff56c2d3c0c3c6728964e349fef8a44d2e Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 13 Jan 2025 14:53:01 +0000 Subject: [PATCH 18/25] Update omopcept --- renv.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/renv.lock b/renv.lock index c11536b..b110984 100644 --- a/renv.lock +++ b/renv.lock @@ -677,11 +677,11 @@ "Version": "0.0.6.1", "Source": "GitHub", "RemoteType": "github", - "RemoteHost": "api.github.com", - "RemoteRepo": "omopcept", "RemoteUsername": "SAFEHR-data", + "RemoteRepo": "omopcept", "RemoteRef": "HEAD", - "RemoteSha": "145c5e82c2f252903dbb5ca52f50a0d841ed09b2", + "RemoteSha": "9aa7e10eb94c6a3442f4de259d7445c341818997", + "RemoteHost": "api.github.com", "Requirements": [ "R", "arrow", @@ -692,7 +692,7 @@ "rlang", "stringr" ], - "Hash": "046e0eba1d9ac70bd15bab91577e19a9" + "Hash": "6f7ccde3675c111b089fb1a9b0a2e84e" }, "openssl": { "Package": "openssl", From 74a18dbd63d4efc7dda5981dcaecb1fb44f0f3db Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 13 Jan 2025 14:53:20 +0000 Subject: [PATCH 19/25] Add project id --- starter-guide.Rproj | 1 + 1 file changed, 1 insertion(+) diff --git a/starter-guide.Rproj b/starter-guide.Rproj index 8e3c2eb..a4c8f96 100644 --- a/starter-guide.Rproj +++ b/starter-guide.Rproj @@ -1,4 +1,5 @@ Version: 1.0 +ProjectId: 8521406b-bc65-40d3-8d66-83ab498b0c5b RestoreWorkspace: Default SaveWorkspace: Default From 7e6e1942303333f27be5b92aa69ff5949c6375f6 Mon Sep 17 00:00:00 2001 From: South Date: Mon, 13 Jan 2025 16:33:09 +0000 Subject: [PATCH 20/25] try to fix Error in `fortify()`:! `data` must be a --- .../02-omop-walkthrough-critical-care.Rmd | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd b/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd index 30c80cc..fbcb4dd 100644 --- a/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd +++ b/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd @@ -123,7 +123,7 @@ omop_named <- omop |> omop_join_name_all() names(omop_named$person) |> str_subset("name") # now the gender name column can be used in the plot -ggplot(omop_named$person, aes(x=year_of_birth, fill = as.factor(gender_concept_name))) + +ggplot(omop_named$person, aes(x=year_of_birth, fill=as.factor(gender_concept_name))) + geom_bar() + theme_minimal() @@ -203,7 +203,12 @@ joined_mp <- omop_named$measurement |> freq_top_measures <- joined_mp |> count(measurement_concept_name,gender_concept_name, sort=TRUE) |> - filter(n > 1) + filter(n > 1) |> + #TODO not sure why collect() needed here + #but without it the following ggplot erros with + #Error in `fortify()`:! `data` must be a , or an object coercible by + #something to do with arrow tables ? + collect() #plot freq_top_measures |> From 55dfc8e12965099c7c1de3b608ecd3c3ff62a7c1 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 13 Jan 2025 17:30:17 +0000 Subject: [PATCH 21/25] Convert dynamic docs to markdown --- .github/workflows/knit-rmd.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index 74cc1fa..e95e4c7 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -36,9 +36,9 @@ jobs: - name: Find and knit Rmd files run: | Rscript -e ' - rmd_files <- list.files(pattern = "\\.Rmd$", recursive = TRUE) + rmd_files <- list.files(path = "dynamic-docs", pattern = "\\.Rmd$", recursive = TRUE) for (file in rmd_files) { - rmarkdown::render(file) + rmarkdown::render(file, output_format = "md_document") } ' From 4e6e8f83108f6c293cb7dfc788974e95d552c504 Mon Sep 17 00:00:00 2001 From: Stef Piatek Date: Mon, 13 Jan 2025 19:06:36 +0000 Subject: [PATCH 22/25] Knit files in the right place --- .github/workflows/knit-rmd.yaml | 4 ++-- .../figure-html/explore-person-1.png | Bin 6209 -> 0 bytes .../figure-html/explore-visit_occurrence-1.png | Bin 6423 -> 0 bytes .../figure-html/join-person-measurement-1.png | Bin 11294 -> 0 bytes .../figure-html/omop-join-names-all-1.png | Bin 6153 -> 0 bytes 5 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 02-omop-walkthrough-critical-care_files/figure-html/explore-person-1.png delete mode 100644 02-omop-walkthrough-critical-care_files/figure-html/explore-visit_occurrence-1.png delete mode 100644 02-omop-walkthrough-critical-care_files/figure-html/join-person-measurement-1.png delete mode 100644 02-omop-walkthrough-critical-care_files/figure-html/omop-join-names-all-1.png diff --git a/.github/workflows/knit-rmd.yaml b/.github/workflows/knit-rmd.yaml index e95e4c7..76608d0 100644 --- a/.github/workflows/knit-rmd.yaml +++ b/.github/workflows/knit-rmd.yaml @@ -36,9 +36,9 @@ jobs: - name: Find and knit Rmd files run: | Rscript -e ' - rmd_files <- list.files(path = "dynamic-docs", pattern = "\\.Rmd$", recursive = TRUE) + rmd_files <- list.files(path = "dynamic-docs", pattern = "\\.Rmd$", recursive = TRUE, full.names = TRUE) for (file in rmd_files) { - rmarkdown::render(file, output_format = "md_document") + rmarkdown::render(file, output_format = "md_document", output_dir = ".") } ' diff --git a/02-omop-walkthrough-critical-care_files/figure-html/explore-person-1.png b/02-omop-walkthrough-critical-care_files/figure-html/explore-person-1.png deleted file mode 100644 index 0d801abf4c1a446c744f76153efb34928fdc9374..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6209 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 diff --git a/02-omop-walkthrough-critical-care_files/figure-html/explore-visit_occurrence-1.png b/02-omop-walkthrough-critical-care_files/figure-html/explore-visit_occurrence-1.png deleted file mode 100644 index df1fe7fa909f3e684301e87df578f070084dc99e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6423 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 MfrWmd?rHMh0rU00%>V!Z diff --git a/02-omop-walkthrough-critical-care_files/figure-html/join-person-measurement-1.png b/02-omop-walkthrough-critical-care_files/figure-html/join-person-measurement-1.png deleted file mode 100644 index 84bf1faac38086798f261d2984973989835d883c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11294 zcma)i1yoes+CL~Il1dG!f`GJubU4yIk^<7wGKkdB0s=}SDLM4O2!ae<(jhT4GKA97 zNay?yzW2N9{qFzXyS}r|tU2fGy`R1Jvw!=^{T`yJL`qCgjDv$is-i5fje~Oyj)Q~y zgXlW&MMImP0C@3)sOu^KuQ)goI5;*q60tZoRXEM<>VQSs|%{35v>6QZlp#uaCh7Mp=g6+V^f6%%Aguh zs75sKgI-<00}>h?4UO)GB9Tz!BG4H?(M37g#YNfW>Z)_8!$$vuB2e$DWi%8S9j$TI z2)K~Q=x%JR1Ws&KY%B(wtPD#2Yd|i^$;mFsb;-#yb;&bWBvb?Wrzd2z##KMaXk<4M zx!8?d#8%nhRAI4oE}%LW$Ko=kcGy@s{^|08h zt^nEqC4dId6pO|BmnVb*jKA?p+0YdShpg@Dhuh_hc!7g+2S-I7tP4xu%!mnKRPyS? zzajfXmD9=9BT}1(`v-dtZ`4y|%Y=gb{5YNYZuFCZ$+$NnVPN5>Upm2iU7ohf8D4Xq zhg~z97wG9#FPW-*Oh(2>Y3bAq=|Rsd-s@nH<9d!H4%jaUoc#$u_=(|7f{-sXB*fOd zbX2`Y0-Onz<`7QD7C2=5KUYAj*w$OtTJ&G{70Ui6dK zj3&<+qDriF$%0L}@Z*p9mn)jj*JJv!E@zug7taPoJ@_ZbwYkE;{E6DZ{(CHQ53~H5 z{SQ_GE@A?X?Rp4IRF?!+^R?UH*o)$mtgO+`GH1vb|I4*6q;-+K7HGBmqPV`H%YkMW zs};_d^Ujy&3udE9C!2fA@wWTIyGRz^|DjILy2_8;48Rs$5iio%OC(Q{3gXLsO}DRI zWPv8XT%XJOj4k1BJs>?os)?)${uxp#!NuaY?NRLI;n?XI#~=>|u7+SFXw=o-`}+Ai zxc}m0DQ0t7)^D2wdM0FX)at~W{rcbYE(s}1=KH8&^#^;sSqprL`0t#?is}k*qR9R; zqwO+_Jz^G`e}3DSlejq?z1J3O$el85V`ge35@&jwM7ul~d-C(|o^6Vh6D0m1y z=4n=c3cq~4C##e@WugU*Dm~50!VYZ7c+5=&tOa?TC9)cHXo}7EK3(!`*qH)ThwsGc zCUC)%ijzcU?tbCfmT2CawL^L8W22UeF1*t=SGHWl7#vVuZ=GWX(KiVCbzY*GoRc!7 zT|G8OBaixCU=r!-Nj*G|$4%Tf@7Ui=<&YH<+&##xlQ8a;=tQ$id?}3%AI{2nW;|8k zq@I|cWRih7*m9C%s2%1w>pIjE;1r#b3NkJb{TWjk%HS3*&%mv7Y)|6^Iqf;+KP-d> zEOuTPH^07ac`lLx8uzhOs7h#V-`fvF=H?W)D5hm^JxekY@xYUQ9k6atr`?QsHv+%t zXO#!hD59mttkK4~am_&((u2X|s*&ogI$!!VI!pvIfXRQ$$`)PL)4t|AL>62u!eCv} zg97X2AF2i{DT7A0otbfip|R&*b&MZ8T=hTxslf!!nwI#%;yFR2dfkL)$^kuDP@T+) zkqIhR-K=(-AtRV6G<5XFBdJrNcgDP*$s8hBQen}ON^^x&4>7qcbT|9Q4uCJ%pQ@Ok z+ThbRlN8^=#W^t=1`eJR0h@V*Z;W7-73FCbhH)Ma5fWVhPPdG5BYx4kMJ-eLRWCqrZjnzSN!Iee=S` z|NeKR_XZW zRC*Hv4nc8}p6UpJUO4;-9R$;j%;}plKH-EV1RDu+WJ7;12#uf=j(hAv(@tMq-d0ixYoEwE7hS{E&N0HX2O0}xJaQP9S zpdgBUrSzns?_57s`!IafPFP+3t&<^C97PrVbG95T_e(Kwe0=HSyGCCwu)wOSdzBNG zi6xJ9b?C()XS(P^M4F1jOR-V9ts0oDft&xzR=*DJ?r&UPR>WO((>}1@t{a}7wEZC; z6L{pBNy*+vyC9>R1SUn(CcZDmI~Ye(pUyX|-D>77Gif1Wcmnf^XGz14kOFP0B&Cp1 zRD89gY$`LZ`964ts7VQ~v*CjFWX5eUF$gC?sa74NMO>!uAUY(8f=l%eQ>{V9TE9|Z zv|2G6@5DaSgXa<^OSu&|x1PRM`O0}W_*GwftiiV6;)Ju_k8irXYy|DPt4yLi~ZNkZIz z_ewO^w9EZBJts6?Aa?+5X^JLFGZwIGnt~zxeed*=za%B-HyBd{AMgfFFJSIYVlKU& zIr}cWc`W{F7vHV|e#&NwDc880_3%<0>A8`gflJ$5KE;NRxe?}0nNFyVx;1-p`s*SW zCG=xn)R5u&ScE3T%N5J{X!RuH$V^s4lC_wSwpnG02hrq*SHeHP#^?XqXHZz;I-kE# zr6I&m$P}X(&fy9fR0xjXmuJ8qJcNCl2eY~ z#S=uLgTVZnX(7~F5AC|PI;QQ-(GjCI79C?-3{d_tb?bH3%~rdKHIwj+1(QEm#J}4D zKfnLd^iDJb>ngsZRoQ%vXwOgfh6;N$x_X?zrZd_C9Wes*Y0;-EJ}svNnfWfWK}XOi z=0u~>{fI}= zw+2p3KvaAU4^_~LZ+!K#k9o@;W>jq-7PV3bN~S)$f8f+r zqysAWP2#;>WY!G3*sIPIL4FAM#*y*hSN|8ewXDXV$t;Ji%ki3I+q-CuV>_~7&G_7< zqebK)J&k+e12jCwticrfkR@Q()<(fnKI{&35O%v9N=SMWCh0p(ZN4UXBbOPI9D}Fe z|DxL0wkvm0z3TR`|HQ=ko22}%umGat6$1<|I9FMHf`DnUt^83=sebc%)x6(jw`}|!dv+VY;Pyer+o$!( z;rFl^m@f>ke!dFXS3YAktN1#$$SQk&TeTB~T`pqbXWCOFjG_)eu|BxFynZ8%JWW$W z?6zLJg>nm_PAq3e@QEKk5XU1xn6jV z)zU=0o=BaxFNZAGgP;03s0ueJ*}?^F6qTY>37AZT$;AtQfv@&{TP80AAFjFXOs4Ub7!wRM&%@ zCM&#rt`n;1GbM%&pBMPS1H7`lQqyDe*-_UNSPsOXQ^0RpjY;sQx?5b8IKpznrwCU3 zK@+@lvbFC_mFaQ*tK#rhbLH>)WA9!q(Yi}-g?4Ycmr^p&ICroghsEfj^>O)0-3HB* zo{zGkona#gQ6x)Rqw^}@d_p=)!$Uj3V zf3m!}{2!R19yTcD&6CviYCZOObdw_e?NiZ;q7_YK=G1(@p-d@LPS5PVpj<)&eg|mO zztin*Y71P2&Rrs5lT>V>D}ebN2FxWAs_M+1!D^tgj}nvEKGB2K)2rAC%O zR9V3^`9R5u@!*)~@8hx}Dr#GZW53Vf#~6cdrewas*nNIM3lBLyD0E0SDdA?NzD^!k zE3*^Z&40%>;p2k*DIh-~9Q_@Vo~6HgNb@6-R$01zUxKnU7%NsjWw~W{xZP!}N!bUb%AB0qs3PS=lDNiQ3WX|GNQt)kOf@s1ZZ7%B9D`VYA zt{<^I$`94ab~vg5bxBXdYc0FbIlo;Y^g~oeys`IU4ir?&ZgifI;(FM$rlh=3(q`aV zy{RWCC5339q%zXA;8RY19;ol?EAsKd>v2+4iU`F9Bl;!Tbx$_;A9436XCfE)2I0qy zZciTsbD@l4;2$cs7{I^2Yb5zvvwsf@zU{Da^C5~yHyzARlFF?#45u%lF`V;2#izT6 z({za=f-|nO@lw3JSHx7dcGKlij!*}Pie-qO#~Ko%FXXeKh!#~yfnDcau0P&ChS7GO z?`{%oFap%dncYl`w02&*5OgT*uLE*>=T^)C{C<&G@DuAI^I(}v5rUz9T0p=3Z)Nv< z{(n2TCG#Yz5ehpjnIS}gBc^XbApM=VwHPg^n*xq7BcE#hq=h>Ywdi$GchI?f*vjiO zoH2sQEYHyd0Ma@(@M+KrZLieth`zkk{59xCZ3prE$nQ=^+9z>)*??t3hN@^TeXE~x zqMuk(q^V90A z`m&1BuvD`}{*`I^D;HL~Uj#Ez$+MJuj-&$8zn26@FyPc#xJ3ndv%c44xTY;dChh|0 zch#81FkIq`lt(G??p$(U1a?y9pkPC-;h`eMatSMERHmRR;CGaZzcq7ZuF4s~D58Nj zl1h+}VOM@#mdbD;JM$039UtaN%jVG?QnBjyOgq%K#R#d>Hr@1BEcS*vwb(ZsM@@s@ zZ1-dI!-~`z9{;lDw>n{4ak@uzNXM)&XeER(tj_VT4ihu z4l(2!go}g{WC>E|0(yJU`!*S`LI()7v*eMidF62dll|GsZ67Ymi)25qA(cA3BYadN6?_j_q0|D;{8aY7tx{->pX6bh9i$-S z0bg1)xi#yY@A8jEw)Z|%Iih;uo?o-2{ig|-u>(QqQOvz^E8lBV90h(%OCEdsmp+&k z&uA)DMkTbe1LS$tTz;Uf(!4@!4R|I0!R*}`%tF^FbyUA0h0%UZ4JB&FR*09g3jU}& z{vzy*+=FF{<>tHZC{Ti6Wz?NieBN|=lx35+#%@9I4O!^*7-^z@t^s)W+D1Gxxc^v* ze?q6pg z6cagF=AME}5jy3;Mp`0SL|d$qgZlnKINEP^2$4jlnv(*8-x1r!{1zqx_+>@at=HP-mZh-{SEdlN{ zdA~`*JMJj}BeASCG5jYe=5LYrX9GoPc{wPuV1IkW&coYyfQ1dHlb{HGRX`^^_k9Ws z={Ti`=PH_W^~i|gNwh_)ee0;#bEa`$|IRcPieJs2rei!v&b#=XXO$K$8hDzQlzGjB z3k^@!BNJZh97?u?;4(c>xRclHPN%!JTg^WqoPfBI(cQmsmTU4c@1oU_klCL0#w4XT z$F1mvT9UEOljr0-i(BP~?^{aX7WC{SAtDSM@wDe|F*qB+w5R7 z<1aZ4zg`0y&lg&aN>;=u?k0Wkv(3vus9h7(I}~XwE1lITYv_*9GjJ&7qeoHlrWJT{ zxcMPED}FzqjiE%*jaiMv8~X_28kTR<+gDF}H^hc*IK@?7gw+HWW+c?`lJr{4S&1Mx z*F1~lcg!J%wcOxOzP%l7@Q!zPW?$e%ZAh|i_7HJZRR8KY$*33AqUMMRTmk zdarw_-^ECmm#m?J~3FP@%-wQ4PN&zj@ zO5**6`t1SS8X*uoe*(|9XCh$oWuu9B3}9st!LJIaJz;G_t^>foxC@{Krs!vQ1sXgQ z4`574^~{GcD{3`R5?cJ_cu4gp}udC#imo$Lt!Bf zFJI~~-1{&+^Kti_vU>@%KdaO1zk7NrLt1ibF^91EXsXj+K?Ys^B4qo*b9B-fP4Ib? zieycOu#zRDbknry-sA))tO_IyfXot)v_=0ghX3C9j$i>p(hZ&bY^c%ujoi|DJF}5l z!uncJgtT!~pj5QN^|JJPJ()ZO)Za?VXSoWE?{&uok_CZjb>H|sl0pU-+z5Y1kPmZk zMrVALIWB2VPJybE?I)h{Tja*nL1SqiQrB0KS9L`_+c0$ebg#Bgp*C46XiGUg_tCiV zl3P}&hh?*J(liqk{k?o4@j?1Kf06jc_Rrhj)o~9i*N9WuKdEcSDGnSA8=4WH5!_2| zLU+=+&vX|5O06L;;HB{yr{`u*wjS_cfOMG|SvA&2+Y(41YAD@i25pGTK8M=I!|lnJ zzkubWDn&S@A#zrAxF(-t3i(kF0z3_|(q5JOWT47K280E;=uQA-d1BM4{sr@D3*<)nx8HM*JuFS$t z6z7rPBZT|nqJz(;>fT>6G+j!-EC4&!OWJNpmax&I_@^P0@Mg>OVLgl)dd^$Y?$&0~ z@L70N!?Vt+ZUtKCr{Tl$B*vZRF!IrO+Ao`o@F~*rA9p_{ zyfT7K$){+AXR4i(R0&yROXkx7p~(-EwlhQTE1T3Wf2JbfZGk@{H%bZ@;v5f7%KuG5 zY*)$&K$St5FfsQk%z)ZRW3%f4pj@NEr3Qo$*? zvV}Z`y`i8S00b>Xkp+Z(^tR0`UH{$)GC|Wp-&~5+doPZBmF7)mA%+@zsr+X9Zj>Zi z`NM2XUzbFR``PBJV6q?cy8*jTJz^Pd{C+kJRutUpWQF%#5!imI55cbI)Spz}shLpQ z-A=^$Egof@ZAkTsTQjGIk_!1TCp8)NlfS2r;kEYS$;V{dvr#1x?y>{SD%1&*Gi$rxu$B)zlbJD7!%Pcug>nBG^BWz-7N-^akdNIf$r6r>H78=83!j-uQtWBb4wJ7_4$Q*bKEfgtc*ZqhquoY9|T zJ$Zq(Y$w-dCvZ}HOKS`H+!b)JM&#jGlko|2@CFHQ5q417J%Pg;(BBXmv4g&>Z04a{4?7{7aG! zrSXENiwzGi>5U-^DO0Cr#$(=^?}vzAkOBEONA;ggE+CNF(6*8#+=eHj?N$+-4yB*s z;2Mc;8~TZ|qfFyvuQoisDSDedsrFN{maj6V4Or+_8VxZGfUR_Qrc{ovN+Jep@s+ls zu6!jf`McLd_1;=s7m%b;4z^?vbDAoac1X3#W&P@C#VHPxxK;h3Ffmf@9XrYSW?(VU z(PsQjNe@vjgNGAbyaIY z$NBV%vkCc2+aGn&TsPY4j=GfOI0(kIx^Y**BZe1Fi3J*I0|Yre8dp>m88bZ#(WSmYr$VHF z-4WEJHnLWq$7a<7h-t2=*Y^`je-Eg^njigal1kfaGcff$w|O!eBI?9L+Pgi~=Q6E8 zzt83m*$&uA|F&MB#hh|5gf0T>O`(1xw~8?%REt(6(A9D(>w3K3@|dgt)*%d91vr1OF`+!zcQ3#}#sUL7Dje-dYd_;8JaPt-ecJHl{yHSKQs$ zO;`R!R@6C1s))abfU*)1BQ>8Jw1|9h zcCVw&#AsvE^3rv06zjj*rW$05t5x~Y#)nJm{6`IZN8B2`k4W)}A<2n*=bI?w{IwX6 zk}9s^DpByhMj>+N_Py)E;#yZ?L-WJneTwONMsO6*D^LxLleK5%7SWbTyKBS>A?Iru zz=7B2JP}7M&d$)@++o-~$00cVw*l>O2@;9pZo|K4UrRo%zy&z3xc6@|-v}+<=~vvo z_N=y-rA~y2`sIC2?(X^QZE#4IQO!?}U=Nqgyy!(2AZ)DufgyTm(I7@V_&n-*a*aJL z{oK+W8M4U&H(^cYqr_8Xm!}i8F$c3eSAptRDr>y*VLrzn9?w@upK(OOC60%-CW>O1 zACy|=iA^Y!&!&Yi4Nek})Jdp7pDBfncxqk85zofKAqHQa1u&JZtR0$yOU&qV#B_bJ z)Q319md`STGFjm@zUraWRSb(D`F&)@5&G;*b167t(Pcycf&A9x?M&xE5^P$-Cfe6m zwkXU|ePp+eqI5HxuCD+W@v*EoT1-A9@&5T?S|IF|LHf!Yd{(T&sZYGwWa^0es^G+Ftqtg0ME55q_Eeta`0;ts`W-gfLa}H zv8k#30g%{^WjC0TH8=YMx4-AO9sk(EB*a(WTJJOew-X1cVe@t0cIrOjP0Jl*vP2)& z!G2Ut6>Qr*n4H3&`!a0kckc>^V{;}>_BO-_^&s#bq&KUY&TVRl`;nc&_hrR;_-y3G zYj00QXkw$$eOWDxfE{!AdF`9Q_|-MSzBEb1G!rfHl-@^oCM&ff?9Tz8+#yrxSi{bh zLK&hxQqMPt-ENwT0W#4AopPtdOS;^uGt>rQJ^31Q=A1b3aUJsg-Q$H=QXhZVSNTTi zq6>;|_AaO0?SyuhVM_f%tSxXa&f$2HtiqwO527)PWNosgWJ*O@EaP3`KCtOztR-$_HEWX3Tuo)Bx^ zeij21DL!<{*flppopcy+nccqZ(ImiyTn1IM0#?hy1Kq4~Z+FEv}m2rZoHdj@7 z<0Q>({luhAe|$wBMPORwyg-v6{m2nlKPkd7TSWj36afz1S0muvnm_64W?1#cZk02G z=kji%V5`sVT4|PSI(PYIS#A@51D1848&2UlMmX|YeAUo5m2_eMxtZU7^|`#BTLL~{ z?7r1rG0rMdu$8cRG@LXV1dh;FEjmgmxov0m89YcHUl?-#pNVxKw)jWtDAQ5>^V@$( zw%;J;{x)6AsD}55xDQXjBXORSF6`nsB*{ggtKFiR$-ec=nv3&|F@M_t`!JIjUm@^-&;?X{G>Z+cp9MQc}=Y+HRpi6dA2A!3Y?AcGw<^+K!3 z;j_h4PkK7H2ftYhS-D%u)hg<#aa$5Z{05$vakxmQSS@^d@O5gOPW%VgwTAlUDKf?n zTHX6qBQ6t{5xHz8xiN@=U8g|i+jHFdfA?Gfz!U(ku>)y|} z>$l5ran`=gOHzk-LODvm+9r@<=TUv{j+h{AAHL+RiMECq->;Q8@8~v3152%@0`^A9 z-wm)!Y)SlRB|q}ZeMn^-#1?r;e_Hw4PDpOhf5iSph#n<|KB~KT(?R4}YH^+riP?E4 z#kLdv22AC5eEX@=tA+fbs=2)HGvRN{y&t5I7fuWKLR{x}#D6R?Xpp54*K zi>@atOS2BUX2iGxU%1{s^PZnwcxm@eX9FzM(G;=Ezi_0g?5k*Z4Me z#2rR28?*M6>4o9_&%h|3?(laD`(;w2+VrH z&?NzCoRJP1AXL-wek~;@%8?xvk6E*SA+UN&cZg7SYdtSyCTbvGoRdL#qn!4|7hDA+ zA;Lb-U1+KCT(1@*PpuQZD`Y5-DPH4oLO*x+3@VzjEWEwy$4S`s@S{0c+G>sC z1i{S0q+%}EnM3;Zf?nicboHt{wzD3#X2EmI2vZm%uYjp&{R=VKQB>PZc)_KL8p5v? z%E#7(J}%FWSzBujuLSX_s3cpU#}F3i#18!tttJ;r>r4@m17eXiA^IN<`9IOtp}*wir0CcZ^{@AkGc@x z6prXL*fJ6ez)(!zweY`DclK;k)ROpPzrF`7Flr^q5F>w^QTuSZQm5m`M2D{(O!<@@ z&}zx85Sn>W*1kFOb&%KRYirvSST;w@ZSI33)+6&<9m5kHc*t#hKIXOC;!Edf*$Wjo z;sL1GOYAoI)MmWOI6MH`=)@$|l$C?#i3F%!W8L`p0Z&0MRF$MR8x!@(X?^Ce=qm?_ z3~;)EyDp;8=lG)%1b0}pqRKHUVE?sr){IDMei%60Yl-CcdC@a_{JKJd`(I~b^6kf~ z%CpFh4eeTo%>u#MC-T!$Ar5N6TxjWbH%T)?!A!Yo_wlM3TauM7ZUU^a3tqk@8(`^_ z6!@Kr=hKl8muQZBsj}rH_?zie;!fwb6ZgN&DKPT?aGKBvkvUCovL0=1 ze`eKs`TRzw{YQV5yf$2jLhH=Vs7W3$aw=6naM~9YwEELTYXsx~@n%+CcagmICUscR znYE${H<+dvUlF|{l@Q(d{MR+s)jp@M@Q~sF|H%N_Ijp))rlh8Q?h&8=I546o*8JJh zo|A12@y|yJQA0D`j6mIdht(DMxm3bo#%q7EeOI*C)SLg~kxJL~k>=wS+v=*)&-nm8 zQ;oA^&PJX4dT0ZxqN~gyc2K|54R^`NrpCYC#GPB=kkWrDlfTdp2A1Z(Sx^5s(1|4< Yn%FPrl~v`qI_ImRpebMa#60N#0V==eqW}N^ diff --git a/02-omop-walkthrough-critical-care_files/figure-html/omop-join-names-all-1.png b/02-omop-walkthrough-critical-care_files/figure-html/omop-join-names-all-1.png deleted file mode 100644 index 790b2e5528a0cf578f8f65d9af66876ed1b671f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6153 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 Date: Mon, 13 Jan 2025 19:10:14 +0000 Subject: [PATCH 23/25] Knit Rmd files --- 02-omop-walkthrough-critical-care.md | 782 +++++++++--------- .../explore-person-1.png | Bin 0 -> 7849 bytes .../explore-visit_occurrence-1.png | Bin 0 -> 9145 bytes .../join-person-measurement-1.png | Bin 0 -> 15113 bytes .../omop-join-names-all-1.png | Bin 0 -> 8174 bytes 5 files changed, 382 insertions(+), 400 deletions(-) create mode 100644 02-omop-walkthrough-critical-care_files/figure-markdown_strict/explore-person-1.png create mode 100644 02-omop-walkthrough-critical-care_files/figure-markdown_strict/explore-visit_occurrence-1.png create mode 100644 02-omop-walkthrough-critical-care_files/figure-markdown_strict/join-person-measurement-1.png create mode 100644 02-omop-walkthrough-critical-care_files/figure-markdown_strict/omop-join-names-all-1.png diff --git a/02-omop-walkthrough-critical-care.md b/02-omop-walkthrough-critical-care.md index b92d48f..c75a8e9 100644 --- a/02-omop-walkthrough-critical-care.md +++ b/02-omop-walkthrough-critical-care.md @@ -1,439 +1,421 @@ +This document is an introductory walkthrough, demonstrating how to read +into R some OMOP data from a series of csv files, join on concept names +and explore and visualise the data. -This document is an introductory walkthrough, demonstrating how to read into R some OMOP data from a series of csv files, join on concept names and explore and visualise the data. +It uses synthetic data created in UCLH as a part of the [Critical Care +Health Informatics Collaborative (CCHIC) +project](https://safehr-data.github.io/uclh-research-discovery/projects/uclh_cchic_s0/index.html). -It uses synthetic data created in UCLH as a part of the [Critical Care Health Informatics Collaborative (CCHIC) project](https://safehr-data.github.io/uclh-research-discovery/projects/uclh_cchic_s0/index.html). +## Installing & loading required packages +If any of the `library($PACKAGE)` packages aren’t installed, you can +install them by running `install.packages("$PACKAGE")`, replacing +`$PACKAGE` with the package name. + # install omopcept from Github if not installed + if (!requireNamespace("omopcept", quietly=TRUE)) + { + if (!requireNamespace("remotes", quietly=TRUE)) install.packages("remotes") + + remotes::install_github("SAFEHR-data/omopcept") + } -## Installing & loading required packages + library(readr) + library(dplyr) + library(here) + library(gh) + library(omopcept) + library(ggplot2) + library(stringr) + library(lubridate) + +## Downloading & reading in OMOP data + +Here we will download & read in some UCLH critical care data stored in +Github (if they are not already present from a previous download). + + repo <- "SAFEHR-data/uclh-research-discovery" + path <- "_projects/uclh_cchic_s0/data" + destdata <- here("dynamic-docs/02-omop-walkthrough-critical-care/data") + + # only download if not already present + if (! file.exists(file.path(destdata,"person.csv"))) + { + # Make GitHub API request to list contents of given path + response <- gh::gh(glue::glue("/repos/{repo}/contents/{path}")) + + # Download all files to the destination dir + purrr::walk(response, ~ download.file(.x$download_url, destfile = file.path(destdata, .x$name))) + + list.files(destdata) + } -``` r -# install omopcept from Github if not installed -if (!requireNamespace("omopcept", quietly=TRUE)) -{ - if (!requireNamespace("remotes", quietly=TRUE)) install.packages("remotes") - - remotes::install_github("SAFEHR-data/omopcept") -} - -library(readr) -library(dplyr) -library(here) -library(gh) -library(omopcept) -library(ggplot2) -library(stringr) -library(lubridate) -``` - -## Downloading & reading in OMOP data - -Here we will download & read in some UCLH critical care data stored in Github (if they are not already present from a previous download). - - -``` r -repo <- "SAFEHR-data/uclh-research-discovery" -path <- "_projects/uclh_cchic_s0/data" -destdata <- here("dynamic-docs/02-omop-walkthrough-critical-care/data") - -# only download if not already present -if (! file.exists(file.path(destdata,"person.csv"))) -{ - # Make GitHub API request to list contents of given path - response <- gh::gh(glue::glue("/repos/{repo}/contents/{path}")) - - # Download all files to the destination dir - purrr::walk(response, ~ download.file(.x$download_url, destfile = file.path(destdata, .x$name))) - - list.files(destdata) -} -``` -## Reading in the OMOP data +## Reading in the OMOP data We now have the OMOP data as a series of csv files in a folder. -The [omopcept package](https://github.com/SAFEHR-data/omopcept) developed at UCLH, and installed above, has a function for reading in OMOP tables to a single list object. - -You could alternatively use [CDMConnector::cdm_from_files](https://darwin-eu.github.io/CDMConnector/reference/cdm_from_files.html) to access OMOP data from files like this and [CDMConnector::cdm_from_con](https://darwin-eu.github.io/CDMConnector/reference/cdm_from_con.html) if your OMOP data are in a database. We aim to add documentation about that here soon. - - -``` r -omop <- omopcept::omop_cdm_read(destdata, filetype="csv") - -# names() can show us names of the tables read in -names(omop) -``` - -``` -## [1] "condition_occurrence" "death" "device_exposure" -## [4] "drug_exposure" "measurement" "observation" -## [7] "observation_period" "person" "procedure_occurrence" -## [10] "specimen" "visit_occurrence" -``` - -## Looking at the `person` table - -The OMOP tables are stored as data frames within the list object & can be accessed by the table name. - -Thus we can find the names of the columns in `person`, use `glimpse()` to preview the data and `ggplot()` plot some of them. Note that not all columns contain data and in that case are filled with `NA`. - - -``` r -# names() can also show column names for one of the tables -names(omop$person) -``` - -``` -## [1] "person_id" "gender_concept_id" -## [3] "year_of_birth" "month_of_birth" -## [5] "day_of_birth" "birth_datetime" -## [7] "race_concept_id" "ethnicity_concept_id" -## [9] "location_id" "provider_id" -## [11] "care_site_id" "person_source_value" -## [13] "gender_source_value" "gender_source_concept_id" -## [15] "race_source_value" "race_source_concept_id" -## [17] "ethnicity_source_value" "ethnicity_source_concept_id" -``` - -``` r -# glimpse table data -glimpse(omop$person) -``` - -``` -## Rows: 100 -## Columns: 18 -## $ person_id 2451, 2452, 2453, 2454, 2455, 2456, 2457, … -## $ gender_concept_id 8532, 8532, 8507, 8507, 8507, 8507, 8507, … -## $ year_of_birth 1947, 1945, 1985, 1948, 1946, 1973, 1979, … -## $ month_of_birth 3, 1, 2, 11, 1, 11, 12, 10, 4, 3, 4, 8, 5,… -## $ day_of_birth 18, 2, 13, 22, 19, 18, 6, 16, 17, 3, 18, 1… -## $ birth_datetime 1947-03-18 11:34:00, 1945-01-02 19:12:41,… -## $ race_concept_id 46285839, 46285825, 46286810, 46286810, 46… -## $ ethnicity_concept_id 38003564, 38003564, 38003563, 38003563, 38… -## $ location_id 97, 92, 70, 32, 91, 93, 1, 40, 30, 16, 26,… -## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ care_site_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ person_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ gender_source_value "FEMALE", "FEMALE", "MALE", "MALE", "MALE"… -## $ gender_source_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ race_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ race_source_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ ethnicity_source_value "Not Hispanic or Latino", "Not Hispanic or… -## $ ethnicity_source_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -``` - -``` r -# plot some columns, patient birth years by gender -ggplot(omop$person, aes(x=year_of_birth, fill = as.factor(gender_concept_id))) + - geom_bar() + - theme_minimal() -``` - -![](02-omop-walkthrough-critical-care_files/figure-html/explore-person-1.png) - -In the plot above bars are coloured by `gender_concept_id` which is the OMOP ID for gender, but we don't actually know which is which. We will look at resolving that by retrieving OMOP concept names in the next section. +The [omopcept package](https://github.com/SAFEHR-data/omopcept) +developed at UCLH, and installed above, has a function for reading in +OMOP tables to a single list object. + +You could alternatively use +[CDMConnector::cdm\_from\_files](https://darwin-eu.github.io/CDMConnector/reference/cdm_from_files.html) +to access OMOP data from files like this and +[CDMConnector::cdm\_from\_con](https://darwin-eu.github.io/CDMConnector/reference/cdm_from_con.html) +if your OMOP data are in a database. We aim to add documentation about +that here soon. + + omop <- omopcept::omop_cdm_read(destdata, filetype="csv") + + # names() can show us names of the tables read in + names(omop) + + ## [1] "condition_occurrence" "death" "device_exposure" + ## [4] "drug_exposure" "measurement" "observation" + ## [7] "observation_period" "person" "procedure_occurrence" + ## [10] "specimen" "visit_occurrence" + +## Looking at the `person` table + +The OMOP tables are stored as data frames within the list object & can +be accessed by the table name. + +Thus we can find the names of the columns in `person`, use `glimpse()` +to preview the data and `ggplot()` plot some of them. Note that not all +columns contain data and in that case are filled with `NA`. + + # names() can also show column names for one of the tables + names(omop$person) + + ## [1] "person_id" "gender_concept_id" + ## [3] "year_of_birth" "month_of_birth" + ## [5] "day_of_birth" "birth_datetime" + ## [7] "race_concept_id" "ethnicity_concept_id" + ## [9] "location_id" "provider_id" + ## [11] "care_site_id" "person_source_value" + ## [13] "gender_source_value" "gender_source_concept_id" + ## [15] "race_source_value" "race_source_concept_id" + ## [17] "ethnicity_source_value" "ethnicity_source_concept_id" + + # glimpse table data + glimpse(omop$person) + + ## Rows: 100 + ## Columns: 18 + ## $ person_id 2451, 2452, 2453, 2454, 2455, 2456, 2457, … + ## $ gender_concept_id 8532, 8532, 8507, 8507, 8507, 8507, 8507, … + ## $ year_of_birth 1947, 1945, 1985, 1948, 1946, 1973, 1979, … + ## $ month_of_birth 3, 1, 2, 11, 1, 11, 12, 10, 4, 3, 4, 8, 5,… + ## $ day_of_birth 18, 2, 13, 22, 19, 18, 6, 16, 17, 3, 18, 1… + ## $ birth_datetime 1947-03-18 11:34:00, 1945-01-02 19:12:41,… + ## $ race_concept_id 46285839, 46285825, 46286810, 46286810, 46… + ## $ ethnicity_concept_id 38003564, 38003564, 38003563, 38003563, 38… + ## $ location_id 97, 92, 70, 32, 91, 93, 1, 40, 30, 16, 26,… + ## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ care_site_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ person_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ gender_source_value "FEMALE", "FEMALE", "MALE", "MALE", "MALE"… + ## $ gender_source_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ race_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ race_source_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ ethnicity_source_value "Not Hispanic or Latino", "Not Hispanic or… + ## $ ethnicity_source_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + + # plot some columns, patient birth years by gender + ggplot(omop$person, aes(x=year_of_birth, fill = as.factor(gender_concept_id))) + + geom_bar() + + theme_minimal() + +![](/home/runner/work/starter-guide/starter-guide/02-omop-walkthrough-critical-care_files/figure-markdown_strict/explore-person-1.png) + +In the plot above bars are coloured by `gender_concept_id` which is the +OMOP ID for gender, but we don’t actually know which is which. We will +look at resolving that by retrieving OMOP concept names in the next +section. ## Getting names for OMOP concept IDs -To get the names for these and other concept IDs we need to use the OMOP vocabularies that store concept IDs and names. In some cases an OMOP database will contain the vocabularies as extra tables. In this case the vocabularies are not provided with the csv files. +To get the names for these and other concept IDs we need to use the OMOP +vocabularies that store concept IDs and names. In some cases an OMOP +database will contain the vocabularies as extra tables. In this case the +vocabularies are not provided with the csv files. -One way to add concept names is to use a function called `omop_join_name_all()` from the [omopcept package](https://github.com/SAFEHR-data/omopcept). It will add columns containing concept names for all columns identified as containing concept ids (based on the column name). It works on single tables but will also accept a list of tables and add name columns to all of them (it can take a good few seconds to join on all the name columns). +One way to add concept names is to use a function called +`omop_join_name_all()` from the [omopcept +package](https://github.com/SAFEHR-data/omopcept). It will add columns +containing concept names for all columns identified as containing +concept ids (based on the column name). It works on single tables but +will also accept a list of tables and add name columns to all of them +(it can take a good few seconds to join on all the name columns). + # join name columns onto all tables + omop_named <- omop |> omop_join_name_all() -``` r -# join name columns onto all tables -omop_named <- omop |> omop_join_name_all() + # the names columns that have been added + names(omop_named$person) |> str_subset("name") -# the names columns that have been added -names(omop_named$person) |> str_subset("name") -``` + ## [1] "gender_concept_name" "race_concept_name" "ethnicity_concept_name" -``` -## [1] "gender_concept_name" "race_concept_name" -## [3] "ethnicity_concept_name" "gender_source_concept_name" -## [5] "race_source_concept_name" "ethnicity_source_concept_name" -``` + # now the gender name column can be used in the plot + ggplot(omop_named$person, aes(x=year_of_birth, fill=as.factor(gender_concept_name))) + + geom_bar() + + theme_minimal() -``` r -# now the gender name column can be used in the plot -ggplot(omop_named$person, aes(x=year_of_birth, fill = as.factor(gender_concept_name))) + - geom_bar() + - theme_minimal() -``` - -![](02-omop-walkthrough-critical-care_files/figure-html/omop-join-names-all-1.png) +![](/home/runner/work/starter-guide/starter-guide/02-omop-walkthrough-critical-care_files/figure-markdown_strict/omop-join-names-all-1.png) ## Looking at the `measurement` table -We can use the `measurement_concept_name` column (that was added by `omop_join_name_all()` above) to see which are the most common measurements. - - -``` r -glimpse(omop_named$measurement) -``` - -``` -## Rows: 100 -## Columns: 26 -## $ measurement_id 2448, 2449, 2450, 2451, 2452, 2453, 24… -## $ person_id 2451, 2452, 2453, 2454, 2455, 2456, 24… -## $ measurement_concept_id 45757366, 45773395, 45763689, 45773403… -## $ measurement_concept_name "Age at smoking cessation", "Anion gap… -## $ measurement_date 1996-06-26, 1985-11-07, 1995-02-06, 1… -## $ measurement_datetime 1996-06-26 12:26:10, 1985-11-07 05:38… -## $ measurement_time NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ measurement_type_concept_id 32817, 32817, 32817, 32817, 32817, 328… -## $ measurement_type_concept_name "EHR", "EHR", "EHR", "EHR", "EHR", "EH… -## $ operator_concept_id 4172704, 4171756, 4171756, 4171755, 41… -## $ operator_concept_name ">", "<", "<", ">=", ">=", ">", "<", "… -## $ value_as_number 91, 83, 89, 60, 115, 124, 34, 34, 151,… -## $ value_as_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ value_as_concept_name NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ unit_concept_id 8555, 8496, 8496, 8648, 8547, 8511, 85… -## $ unit_concept_name "second", "femtoliter platelet mean vo… -## $ range_low NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ range_high NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ visit_occurrence_id 2451, 2452, 2453, 2454, 2455, 2456, 24… -## $ visit_detail_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ measurement_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ measurement_source_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ measurement_source_concept_name NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ unit_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ value_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -``` - -``` r -# most frequent measurement concepts -count(omop_named$measurement, measurement_concept_name, sort=TRUE) -``` - -``` -## # A tibble: 60 × 2 -## measurement_concept_name n -## -## 1 Direct site 4 -## 2 12 month target weight 3 -## 3 BK polyomavirus DNA (deoxyribonucleic acid) detection assay 3 -## 4 Detection of lymphocytes positive for CD8 antigen 3 -## 5 Dietary fluoride intake 3 -## 6 Disabilities of the arm shoulder and hand outcome measure work module … 3 -## 7 Kapandji clinical opposition and reposition test of thumb score 3 -## 8 Knowledge level of traditional therapy 3 -## 9 Peritoneal dialysate collection compliance 3 -## 10 Prescription observable 3 -## # ℹ 50 more rows -``` +We can use the `measurement_concept_name` column (that was added by +`omop_join_name_all()` above) to see which are the most common +measurements. + + glimpse(omop_named$measurement) + + ## Table + ## 100 rows x 24 columns + ## $ measurement_id 2448, 2449, 2450, 2451, 2452, 245… + ## $ person_id 2451, 2452, 2453, 2454, 2455, 245… + ## $ measurement_concept_id 45757366, 45773395, 45763689, 457… + ## $ measurement_concept_name "Age at smoking cessation", "Anio… + ## $ measurement_date 1996-06-26, 1985-11-07, 1995-02-0… + ## $ measurement_datetime 1996-06-26 12:26:10, 1985-11-07 0… + ## $ measurement_time NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ measurement_type_concept_id 32817, 32817, 32817, 32817, 32817… + ## $ measurement_type_concept_name "EHR", "EHR", "EHR", "EHR", "EHR"… + ## $ operator_concept_id 4172704, 4171756, 4171756, 417175… + ## $ operator_concept_name ">", "<", "<", ">=", ">=", ">", "… + ## $ value_as_number 91, 83, 89, 60, 115, 124, 34, 34,… + ## $ value_as_concept_id NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ unit_concept_id 8555, 8496, 8496, 8648, 8547, 851… + ## $ unit_concept_name "second", "femtoliter platelet me… + ## $ range_low NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ range_high NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ visit_occurrence_id 2451, 2452, 2453, 2454, 2455, 245… + ## $ visit_detail_id NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ measurement_source_value NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ measurement_source_concept_id NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ unit_source_value NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ value_source_value NA, NA, NA, NA, NA, NA, NA, NA, N… + ## Call `print()` for full schema details + + # most frequent measurement concepts + count(omop_named$measurement, measurement_concept_name, sort=TRUE) + + ## Table (query) + ## measurement_concept_name: string + ## n: int64 + ## + ## * Sorted by n [desc] + ## See $.data for the source Arrow object ## Looking at the `observation` table -We can use the `observation_concept_name` column (that was added by `omop_join_name_all()` above) to see which are the most common observations. - - -``` r -glimpse(omop_named$observation) -``` - -``` -## Rows: 100 -## Columns: 24 -## $ observation_id 2444, 2446, 2448, 2451, 2453, 2454, 24… -## $ person_id 2452, 2454, 2456, 2459, 2461, 2462, 24… -## $ observation_concept_id 706011, 704996, 715751, 703437, 723488… -## $ observation_concept_name "Metastasis", "Patient meets COVID-19 … -## $ observation_date 1975-02-21, 2009-03-31, 2021-10-16, 1… -## $ observation_datetime 1975-02-21 18:56:45, 2009-03-31 17:14… -## $ observation_type_concept_id 32868, 32840, 32813, 32818, 32830, 328… -## $ observation_type_concept_name "Payer system record (secondary payer)… -## $ value_as_number NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ value_as_string NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ value_as_concept_id 715268, 715740, 706014, 710686, 703430… -## $ value_as_concept_name "COVID-19 Intubation Procedure note", … -## $ qualifier_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ qualifier_concept_name NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ unit_concept_id 44777585, 44777541, 44777573, 44777545… -## $ unit_concept_name "million allergen-specific IgE antibod… -## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ visit_occurrence_id 2452, 2454, 2456, 2459, 2461, 2462, 24… -## $ visit_detail_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ observation_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ observation_source_concept_id 715745, 706008, 715738, 710690, 706004… -## $ observation_source_concept_name "Advice given about 2019-nCoV (novel c… -## $ unit_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -## $ qualifier_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… -``` - -``` r -# most frequent observation concepts -count(omop_named$observation, observation_concept_name, sort=TRUE) -``` - -``` -## # A tibble: 55 × 2 -## observation_concept_name n -## -## 1 9 -## 2 Assault by unspecified gases and vapours 4 -## 3 City of travel [Location] 4 -## 4 Advice given about 2019-nCoV (novel coronavirus) infection by telephone 3 -## 5 Assault by other specified gases and vapours 3 -## 6 COVID-19 Intubation Progress note 3 -## 7 Exposure to 2019-nCoV (novel coronavirus) infection 3 -## 8 Family history with explicit context pertaining to sibling 3 -## 9 Metastasis 3 -## 10 Retired SNOMED UK Drug extension concept, do not use, use concept indi… 3 -## # ℹ 45 more rows -``` +We can use the `observation_concept_name` column (that was added by +`omop_join_name_all()` above) to see which are the most common +observations. + + glimpse(omop_named$observation) + + ## Rows: 100 + ## Columns: 23 + ## $ observation_id 2444, 2446, 2448, 2451, 2453, 2454, 24… + ## $ person_id 2452, 2454, 2456, 2459, 2461, 2462, 24… + ## $ observation_concept_id 706011, 704996, 715751, 703437, 723488… + ## $ observation_concept_name "Metastasis", "Patient meets COVID-19 … + ## $ observation_date 1975-02-21, 2009-03-31, 2021-10-16, 1… + ## $ observation_datetime 1975-02-21 18:56:45, 2009-03-31 17:14… + ## $ observation_type_concept_id 32868, 32840, 32813, 32818, 32830, 328… + ## $ observation_type_concept_name "Payer system record (secondary payer)… + ## $ value_as_number NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ value_as_string NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ value_as_concept_id 715268, 715740, 706014, 710686, 703430… + ## $ value_as_concept_name "COVID-19 Intubation Procedure note", … + ## $ qualifier_concept_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ unit_concept_id 44777585, 44777541, 44777573, 44777545… + ## $ unit_concept_name "million allergen-specific IgE antibod… + ## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ visit_occurrence_id 2452, 2454, 2456, 2459, 2461, 2462, 24… + ## $ visit_detail_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ observation_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ observation_source_concept_id 715745, 706008, 715738, 710690, 706004… + ## $ observation_source_concept_name "Advice given about 2019-nCoV (novel c… + ## $ unit_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + ## $ qualifier_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA… + + # most frequent observation concepts + count(omop_named$observation, observation_concept_name, sort=TRUE) + + ## # A tibble: 55 × 2 + ## observation_concept_name n + ## + ## 1 9 + ## 2 Assault by unspecified gases and vapours 4 + ## 3 City of travel [Location] 4 + ## 4 Advice given about 2019-nCoV (novel coronavirus) infection by telephone 3 + ## 5 Assault by other specified gases and vapours 3 + ## 6 COVID-19 Intubation Progress note 3 + ## 7 Exposure to 2019-nCoV (novel coronavirus) infection 3 + ## 8 Family history with explicit context pertaining to sibling 3 + ## 9 Metastasis 3 + ## 10 Retired SNOMED UK Drug extension concept, do not use, use concept indi… 3 + ## # ℹ 45 more rows ## Looking at the `drug_exposure` table -We can use the `drug_concept_name` column (that was added by `omop_join_name_all()` above) to see which are the most common drugs. - - -``` r -glimpse(omop_named$drug_exposure) -``` - -``` -## Rows: 100 -## Columns: 27 -## $ drug_exposure_id 2443, 2444, 2445, 2446, 2447, 2448, 2449,… -## $ person_id 2451, 2452, 2453, 2454, 2455, 2456, 2457,… -## $ drug_concept_id 44818407, 44818490, 44818425, 44818479, 4… -## $ drug_concept_name "potassium bicarbonate 25 MEQ Effervescen… -## $ drug_exposure_start_date 2004-06-11, 1981-12-14, 1994-10-31, 1961… -## $ drug_exposure_start_datetime 2004-06-11 17:28:54, 1981-12-14 08:28:09… -## $ drug_exposure_end_date 2009-07-12, 1990-01-08, 1996-06-07, 1987… -## $ drug_exposure_end_datetime 2009-07-12 02:31:47, 1990-01-08 15:33:59… -## $ verbatim_end_date NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ drug_type_concept_id 38000180, 43542358, 32426, 38000177, 3800… -## $ drug_type_concept_name "Inpatient administration", "Physician ad… -## $ stop_reason NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ refills NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ quantity 6, 6, 6, 6, 5, 6, 5, 5, 5, 6, 6, 6, 5, 5,… -## $ days_supply NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ sig NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ route_concept_id 4156705, 4167540, 40492305, 40490898, 600… -## $ route_concept_name "Intracardiac", "Enteral", "Intrapericard… -## $ lot_number NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ visit_occurrence_id 2451, 2452, 2453, 2454, 2455, 2456, 2457,… -## $ visit_detail_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ drug_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ drug_source_concept_id 21183732, 21179371, 21217483, 21182589, 2… -## $ drug_source_concept_name "Noristerat 200mg/1ml solution for inject… -## $ route_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -## $ dose_unit_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… -``` - -``` r -# most frequent drug_exposure concepts -count(omop_named$drug_exposure, drug_concept_name, sort=TRUE) -``` - -``` -## # A tibble: 61 × 2 -## drug_concept_name n -## -## 1 Lotus corniculatus flower volatile oil 5 -## 2 thyroid (USP) 81.25 MG Oral Tablet [Nature-Throid] 4 -## 3 Amomum villosum var. xanthioides whole extract 3 -## 4 Glycyrrhiza uralensis whole extract 3 -## 5 hydrocortisone 0.5 MG/ML / lidocaine hydrochloride 0.5 MG/ML / pramoxi… 3 -## 6 salicylic acid 2.5 MG/ML / sodium thiosulfate 1 MG/ML Medicated Shampoo 3 -## 7 toltrazuril 3 -## 8 zinc sulfate 125 MG Effervescent Oral Tablet 3 -## 9 0.1 ML influenza A virus vaccine, A-Victoria-361-2011 (H3N2)-like viru… 2 -## 10 Aesculus hippocastanum seed oil 2 -## # ℹ 51 more rows -``` +We can use the `drug_concept_name` column (that was added by +`omop_join_name_all()` above) to see which are the most common drugs. + + glimpse(omop_named$drug_exposure) + + ## Rows: 100 + ## Columns: 27 + ## $ drug_exposure_id 2443, 2444, 2445, 2446, 2447, 2448, 2449,… + ## $ person_id 2451, 2452, 2453, 2454, 2455, 2456, 2457,… + ## $ drug_concept_id 44818407, 44818490, 44818425, 44818479, 4… + ## $ drug_concept_name "potassium bicarbonate 25 MEQ Effervescen… + ## $ drug_exposure_start_date 2004-06-11, 1981-12-14, 1994-10-31, 1961… + ## $ drug_exposure_start_datetime 2004-06-11 17:28:54, 1981-12-14 08:28:09… + ## $ drug_exposure_end_date 2009-07-12, 1990-01-08, 1996-06-07, 1987… + ## $ drug_exposure_end_datetime 2009-07-12 02:31:47, 1990-01-08 15:33:59… + ## $ verbatim_end_date NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ drug_type_concept_id 38000180, 43542358, 32426, 38000177, 3800… + ## $ drug_type_concept_name "Inpatient administration", "Physician ad… + ## $ stop_reason NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ refills NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ quantity 6, 6, 6, 6, 5, 6, 5, 5, 5, 6, 6, 6, 5, 5,… + ## $ days_supply NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ sig NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ route_concept_id 4156705, 4167540, 40492305, 40490898, 600… + ## $ route_concept_name "Intracardiac", "Enteral", "Intrapericard… + ## $ lot_number NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ visit_occurrence_id 2451, 2452, 2453, 2454, 2455, 2456, 2457,… + ## $ visit_detail_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ drug_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ drug_source_concept_id 21183732, 21179371, 21217483, 21182589, 2… + ## $ drug_source_concept_name "Noristerat 200mg/1ml solution for inject… + ## $ route_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + ## $ dose_unit_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N… + + # most frequent drug_exposure concepts + count(omop_named$drug_exposure, drug_concept_name, sort=TRUE) + + ## # A tibble: 61 × 2 + ## drug_concept_name n + ## + ## 1 Lotus corniculatus flower volatile oil 5 + ## 2 thyroid (USP) 81.25 MG Oral Tablet [Nature-Throid] 4 + ## 3 Amomum villosum var. xanthioides whole extract 3 + ## 4 Glycyrrhiza uralensis whole extract 3 + ## 5 hydrocortisone 0.5 MG/ML / lidocaine hydrochloride 0.5 MG/ML / pramoxi… 3 + ## 6 salicylic acid 2.5 MG/ML / sodium thiosulfate 1 MG/ML Medicated Shampoo 3 + ## 7 toltrazuril 3 + ## 8 zinc sulfate 125 MG Effervescent Oral Tablet 3 + ## 9 0.1 ML influenza A virus vaccine, A-Victoria-361-2011 (H3N2)-like viru… 2 + ## 10 Aesculus hippocastanum seed oil 2 + ## # ℹ 51 more rows ## Looking at the `visit_occurrence` table -The `visit_occurrence` table contains times and attributes of visits. Other tables (e.g. `measurement` & `observation`) have a `visit_occurrence_id` column that can be used to establish the visit that they were associated with. Visits have a start & end date, in these synthetic data the interval between them can be substantial. - - -``` r -glimpse(omop_named$visit_occurrence) -``` - -``` -## Rows: 100 -## Columns: 22 -## $ visit_occurrence_id 2451, 2452, 2453, 2454, 2455, 2456, 2457… -## $ person_id 2451, 2452, 2453, 2454, 2455, 2456, 2457… -## $ visit_concept_id 9203, 9203, 9203, 9203, 9201, 9201, 9201… -## $ visit_concept_name "Emergency Room Visit", "Emergency Room … -## $ visit_start_date 1992-07-23, 1949-01-14, 1994-02-10, 195… -## $ visit_start_datetime 1992-07-23 21:20:23, 1949-01-14 22:11:4… -## $ visit_end_date 2015-09-09, 1991-01-29, 1998-04-24, 201… -## $ visit_end_datetime 2015-09-09 19:12:40, 1991-01-29 22:07:5… -## $ visit_type_concept_id 32817, 32817, 32817, 32817, 32817, 32817… -## $ visit_type_concept_name "EHR", "EHR", "EHR", "EHR", "EHR", "EHR"… -## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, … -## $ care_site_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, … -## $ visit_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, … -## $ visit_source_concept_id 9203, 9201, 9203, 9201, 9203, 9201, 9203… -## $ visit_source_concept_name "Emergency Room Visit", "Inpatient Visit… -## $ admitting_source_concept_id 8882, 8536, 8761, 8970, 8546, 8905, 8968… -## $ admitting_source_concept_name "Adult Living Care Facility", "Home", "R… -## $ admitting_source_value "Adult Living Care Facility", "Home", "R… -## $ discharge_to_concept_id 8716, 8615, 8977, 8870, 8536, 8905, 5814… -## $ discharge_to_concept_name "Independent Clinic", "Assisted Living F… -## $ discharge_to_source_value "Independent Clinic", "Assisted Living F… -## $ preceding_visit_occurrence_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, … -``` - -``` r -# plot timeline of visit starts -omop_named$visit_occurrence |> - #ggplot(aes(x=visit_start_date)) + geom_bar() + - #replacing above with year tally otherwise bars too narrow to be reliably visible - group_by(visit_concept_name, year = lubridate::floor_date(visit_start_date, "year")) |> - summarize(nvisits = n()) |> - ungroup() |> - ggplot(aes(x = year, y = nvisits, fill=visit_concept_name)) + - geom_col() + - facet_grid(vars(as.factor(visit_concept_name))) + - theme_minimal() + - theme(legend.position = "none") -``` - -![](02-omop-walkthrough-critical-care_files/figure-html/explore-visit_occurrence-1.png) - +The `visit_occurrence` table contains times and attributes of visits. +Other tables (e.g. `measurement` & `observation`) have a +`visit_occurrence_id` column that can be used to establish the visit +that they were associated with. Visits have a start & end date, in these +synthetic data the interval between them can be substantial. + + glimpse(omop_named$visit_occurrence) + + ## Rows: 100 + ## Columns: 22 + ## $ visit_occurrence_id 2451, 2452, 2453, 2454, 2455, 2456, 2457… + ## $ person_id 2451, 2452, 2453, 2454, 2455, 2456, 2457… + ## $ visit_concept_id 9203, 9203, 9203, 9203, 9201, 9201, 9201… + ## $ visit_concept_name "Emergency Room Visit", "Emergency Room … + ## $ visit_start_date 1992-07-23, 1949-01-14, 1994-02-10, 195… + ## $ visit_start_datetime 1992-07-23 21:20:23, 1949-01-14 22:11:4… + ## $ visit_end_date 2015-09-09, 1991-01-29, 1998-04-24, 201… + ## $ visit_end_datetime 2015-09-09 19:12:40, 1991-01-29 22:07:5… + ## $ visit_type_concept_id 32817, 32817, 32817, 32817, 32817, 32817… + ## $ visit_type_concept_name "EHR", "EHR", "EHR", "EHR", "EHR", "EHR"… + ## $ provider_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, … + ## $ care_site_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, … + ## $ visit_source_value NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, … + ## $ visit_source_concept_id 9203, 9201, 9203, 9201, 9203, 9201, 9203… + ## $ visit_source_concept_name "Emergency Room Visit", "Inpatient Visit… + ## $ admitting_source_concept_id 8882, 8536, 8761, 8970, 8546, 8905, 8968… + ## $ admitting_source_concept_name "Adult Living Care Facility", "Home", "R… + ## $ admitting_source_value "Adult Living Care Facility", "Home", "R… + ## $ discharge_to_concept_id 8716, 8615, 8977, 8870, 8536, 8905, 5814… + ## $ discharge_to_concept_name "Independent Clinic", "Assisted Living F… + ## $ discharge_to_source_value "Independent Clinic", "Assisted Living F… + ## $ preceding_visit_occurrence_id NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, … + + # plot timeline of visit starts + omop_named$visit_occurrence |> + #ggplot(aes(x=visit_start_date)) + geom_bar() + + #replacing above with year tally otherwise bars too narrow to be reliably visible + group_by(visit_concept_name, year = lubridate::floor_date(visit_start_date, "year")) |> + summarize(nvisits = n()) |> + ungroup() |> + ggplot(aes(x = year, y = nvisits, fill=visit_concept_name)) + + geom_col() + + facet_grid(vars(as.factor(visit_concept_name))) + + theme_minimal() + + theme(legend.position = "none") + +![](/home/runner/work/starter-guide/starter-guide/02-omop-walkthrough-critical-care_files/figure-markdown_strict/explore-visit_occurrence-1.png) ## Joining `person` data to other tables -The OMOP common data model is person centred. Most tables have a `person_id` column that can be used to relate these data to other attributes of the patient. Here we show how we can join the `measurement` and `person` tables to see if there is any gender difference in measurements. A similar approach could be used to join to other tables including `observation` & `drug_exposure`. - - -``` r -joined_mp <- omop_named$measurement |> - left_join(omop_named$person, by="person_id") - -freq_top_measures <- joined_mp |> - count(measurement_concept_name,gender_concept_name, sort=TRUE) |> - filter(n > 1) - -#plot -freq_top_measures |> - ggplot(aes(y=measurement_concept_name, x=n, fill=as.factor(gender_concept_name))) + - geom_col() + - facet_wrap(vars(as.factor(gender_concept_name))) + - theme_minimal() + - theme(legend.position = "none") -``` - -![](02-omop-walkthrough-critical-care_files/figure-html/join-person-measurement-1.png) - -Note that we use `left_join` here because we only want to join on `person` information for rows occurring in the `measurement` table which is the left hand argument of the join. Also note that in this example we end up with one row per patient because the synthetic `measurement` table only has one row per patient. Usually we would expect multiple measurements per patient that would result in multiple rows per patient in the joined table. +The OMOP common data model is person centred. Most tables have a +`person_id` column that can be used to relate these data to other +attributes of the patient. Here we show how we can join the +`measurement` and `person` tables to see if there is any gender +difference in measurements. A similar approach could be used to join to +other tables including `observation` & `drug_exposure`. + + joined_mp <- omop_named$measurement |> + left_join(omop_named$person, by="person_id") + + freq_top_measures <- joined_mp |> + count(measurement_concept_name,gender_concept_name, sort=TRUE) |> + filter(n > 1) |> + #TODO not sure why collect() needed here + #but without it the following ggplot erros with + #Error in `fortify()`:! `data` must be a , or an object coercible by + #something to do with arrow tables ? + collect() + + #plot + freq_top_measures |> + ggplot(aes(y=measurement_concept_name, x=n, fill=as.factor(gender_concept_name))) + + geom_col() + + facet_wrap(vars(as.factor(gender_concept_name))) + + theme_minimal() + + theme(legend.position = "none") + +![](/home/runner/work/starter-guide/starter-guide/02-omop-walkthrough-critical-care_files/figure-markdown_strict/join-person-measurement-1.png) + +Note that we use `left_join` here because we only want to join on +`person` information for rows occurring in the `measurement` table which +is the left hand argument of the join. Also note that in this example we +end up with one row per patient because the synthetic `measurement` +table only has one row per patient. Usually we would expect multiple +measurements per patient that would result in multiple rows per patient +in the joined table. ## Differences between these synthetic data and real patient data -These particular synthetic data are useful to demonstrate the reading in and manipulation of OMOP data but there are some major differences between them and real patient data. +These particular synthetic data are useful to demonstrate the reading in +and manipulation of OMOP data but there are some major differences +between them and real patient data. -1. `person`, `measurement`, `observation` & `drug_exposure` tables are all same length (100 rows), in real data one would expect many more measurements, observations & drug exposures than patients -2. Related to 1, in these data there are a single `measurement`, `observation` and `drug_exposure` per patient. In reality one would expect many tens or hundreds of these other values per patient. +1. `person`, `measurement`, `observation` & `drug_exposure` tables are + all same length (100 rows), in real data one would expect many more + measurements, observations & drug exposures than patients +2. Related to 1, in these data there are a single `measurement`, + `observation` and `drug_exposure` per patient. In reality one would + expect many tens or hundreds of these other values per patient. diff --git a/02-omop-walkthrough-critical-care_files/figure-markdown_strict/explore-person-1.png b/02-omop-walkthrough-critical-care_files/figure-markdown_strict/explore-person-1.png new file mode 100644 index 0000000000000000000000000000000000000000..3d5da2d68c7822ddcfa2fd6c4284740c2b795c2e GIT binary patch literal 7849 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 literal 0 HcmV?d00001 diff --git a/02-omop-walkthrough-critical-care_files/figure-markdown_strict/join-person-measurement-1.png b/02-omop-walkthrough-critical-care_files/figure-markdown_strict/join-person-measurement-1.png new file mode 100644 index 0000000000000000000000000000000000000000..a95d931506165f3a839d3b21654b34d055e0f249 GIT binary patch literal 15113 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

;2c57zQ9`9+3 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 Date: Mon, 13 Jan 2025 19:15:24 +0000 Subject: [PATCH 24/25] Update instructions for knitting --- .../02-omop-walkthrough-critical-care.Rmd | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd b/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd index fbcb4dd..708d11c 100644 --- a/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd +++ b/dynamic-docs/02-omop-walkthrough-critical-care/02-omop-walkthrough-critical-care.Rmd @@ -7,7 +7,10 @@ author: Andy South date: "2024-12-03" --- - + This document is an introductory walkthrough, demonstrating how to read into R some OMOP data from a series of csv files, join on concept names and explore and visualise the data. From 22b42e5c0824f0ddfe88297519ec2c06aba7fa12 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jan 2025 19:17:36 +0000 Subject: [PATCH 25/25] Knit Rmd files --- 02-omop-walkthrough-critical-care.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/02-omop-walkthrough-critical-care.md b/02-omop-walkthrough-critical-care.md index c75a8e9..2bbad08 100644 --- a/02-omop-walkthrough-critical-care.md +++ b/02-omop-walkthrough-critical-care.md @@ -1,4 +1,7 @@ - + This document is an introductory walkthrough, demonstrating how to read into R some OMOP data from a series of csv files, join on concept names