88 Commits
Author SHA1 Message Date
dr. M.S. (Matthijs) Berends 0fdabff1ba (v1.5.0.9023) mo properties speed improvement 2021-02-21 23:19:40 +01:00
dr. M.S. (Matthijs) Berends 062c49fca1 (v1.5.0.9022) mo properties speed improvement 2021-02-21 22:56:35 +01:00
dr. M.S. (Matthijs) Berends 5ef8cb41a7 (v1.5.0.9021) improve speed of %like% 2021-02-21 20:15:09 +01:00
dr. M.S. (Matthijs) Berends daa12ced2c (v1.5.0.9020) translation fix 2021-02-18 23:23:14 +01:00
dr. M.S. (Matthijs) Berends 601ea7377c (v1.5.0.9019) use functions without loading AMR pkg 2021-02-17 10:58:13 +01:00
dr. M.S. (Matthijs) Berends 2dd0656355 (v1.5.0.9018) fix unit tests 2021-02-09 12:28:15 +01:00
dr. M.S. (Matthijs) Berends cb404492b2 (v1.5.0.9017) unit testing 2021-02-08 21:09:36 +01:00
dr. M.S. (Matthijs) Berends 4a84894f79 (v1.5.0.9016) only_rsi_columns update, documentation 2021-02-08 14:18:42 +01:00
dr. M.S. (Matthijs) Berends 8fda473e49 (v1.5.0.9015) unit test fix, grouped first isolates 2021-02-04 16:48:16 +01:00
dr. M.S. (Matthijs) Berends 2eca8c3f01 (v1.5.0.9014) only_rsi_columns, is.rsi.eligible improvement 2021-02-02 23:57:35 +01:00
dr. M.S. (Matthijs) Berends 20d638c193 (v1.5.0.9013) updated tibble printing colours 2021-01-28 16:09:30 +01:00
dr. M.S. (Matthijs) Berends 331c1f6508 (v1.5.0.9012) ampc_cephalosporin_resistance for I 2021-01-25 21:58:00 +01:00
dr. M.S. (Matthijs) Berends 24eb4453db (v1.5.0.9011) small dosage update 2021-01-24 23:27:11 +01:00
dr. M.S. (Matthijs) Berends 286eaa9699 (v1.5.0.9010) MDRO vignette update, get_episode for < day 2021-01-24 14:48:56 +01:00
dr. M.S. (Matthijs) Berends 1a88caa119 (v1.5.0.9009) unit test fixes 2021-01-22 10:55:07 +01:00
dr. M.S. (Matthijs) Berends 1ba44776a1 (v1.5.0.9008) Internal data sets to pkg, speed for auto col determination 2021-01-22 10:20:41 +01:00
dr. M.S. (Matthijs) Berends 27f084d819 (v1.5.0.9007) updated unit tests 2021-01-18 18:45:43 +01:00
dr. M.S. (Matthijs) Berends 4eab095306 (v1.5.0.9006) major documentation update 2021-01-18 16:57:56 +01:00
dr. M.S. (Matthijs) Berends e95218c0d1 (v1.5.0.9005) custom MDRO guideline 2021-01-17 10:35:21 +01:00
dr. M.S. (Matthijs) Berends e699de955c (v1.5.0.9004) custom MDRO guideline 2021-01-17 00:26:48 +01:00
dr. M.S. (Matthijs) Berends 7ebc534ccd (v1.5.0.9003) verbose output of mdro() 2021-01-15 22:44:52 +01:00
dr. M.S. (Matthijs) Berends 6745f3fb17 (v1.5.0.9002) doc update 2021-01-14 15:51:41 +01:00
dr. M.S. (Matthijs) Berends bc00470dca (v1.5.0.9001) more informative argument errors 2021-01-14 14:41:44 +01:00
dr. M.S. (Matthijs) Berends d014955ce0 (v.1.5.0.9000) implementation of EUCAST rules v11 (2021) 2021-01-12 22:08:04 +01:00
dr. M.S. (Matthijs) Berends 3b84b8be75 v1.5.0 2021-01-06 11:16:17 +01:00
dr. M.S. (Matthijs) Berends 1563dcd1aa (v1.4.0.9062) unit test fix 2021-01-04 14:46:17 +01:00
dr. M.S. (Matthijs) Berends a7ea4c9d2f (v1.4.0.9061) ab class selector fix 2021-01-04 14:16:09 +01:00
dr. M.S. (Matthijs) Berends 8d117820b8 (v1.4.0.9060) ab class selector fix 2021-01-04 13:39:06 +01:00
dr. M.S. (Matthijs) Berends c9de74c81a (v1.4.0.9059) ab class selector fix 2021-01-04 12:29:25 +01:00
dr. M.S. (Matthijs) Berends 82cfa24ea4 (v1.4.0.9058) GH actions update 2021-01-04 11:27:37 +01:00
dr. M.S. (Matthijs) Berends daac96fefe (v1.4.0.9057) GH actions update 2021-01-04 09:49:42 +01:00
dr. M.S. (Matthijs) Berends 63a4dda467 (v1.4.0.9056) subsetting ab class selectors for base R 2021-01-03 23:40:05 +01:00
dr. M.S. (Matthijs) Berends ecac443f86 (v1.4.0.9055) more unit tests 2020-12-31 13:44:58 +01:00
dr. M.S. (Matthijs) Berends 10dec96058 (v1.4.0.9054) unit test update 2020-12-29 22:06:01 +01:00
dr. M.S. (Matthijs) Berends d3f007bf65 (v1.4.0.9053) unit test old R versions 2020-12-29 21:23:01 +01:00
dr. M.S. (Matthijs) Berends 526f8afb08 (v1.4.0.9052) replaced all sapply's with type-safe vapply's 2020-12-28 22:24:33 +01:00
dr. M.S. (Matthijs) Berends ccf13dd6c0 (v1.4.0.9051) ab class 2020-12-27 23:19:41 +01:00
dr. M.S. (Matthijs) Berends afc325c314 (v1.4.0.9050) ab selectors base R 2020-12-27 20:32:40 +01:00
dr. M.S. (Matthijs) Berends 175e33abba (v1.4.0.9049) unit tests 2020-12-27 15:07:01 +01:00
dr. M.S. (Matthijs) Berends ed198916bf (v1.4.0.9048) AmpC de-repressed cephalo-resistant mutants 2020-12-27 14:23:11 +01:00
dr. M.S. (Matthijs) Berends 8b52f9b1be (v1.4.0.9047) unit tests 2020-12-27 00:30:28 +01:00
dr. M.S. (Matthijs) Berends acbd0cf7ca (v1.4.0.9046) get_episode 2020-12-27 00:07:00 +01:00
dr. M.S. (Matthijs) Berends 291f802be3 (v1.4.0.9045) unit tests 2020-12-25 00:06:11 +01:00
dr. M.S. (Matthijs) Berends df37584189 (v1.4.0.9044) mo tibble printing, mo_shortname() fix 2020-12-24 23:29:10 +01:00
dr. M.S. (Matthijs) Berends 128ebcfd62 (v1.4.0.9043) documentation update 2020-12-22 00:51:17 +01:00
dr. M.S. (Matthijs) Berends ee70883246 (v1.4.0.9042) auto dark theme website 2020-12-21 22:46:29 +01:00
dr. M.S. (Matthijs) Berends 81af41da3a (v1.4.0.9041) updates based on review 2020-12-17 16:22:25 +01:00
dr. M.S. (Matthijs) Berends 1faa816090 (v1.4.0.9040) LA-MRSA / CA-MRSA 2020-12-16 16:18:53 +01:00
dr. M.S. (Matthijs) Berends 203bc20eb0 (v1.4.0.9039) more unit tests 2020-12-13 20:44:32 +01:00
dr. M.S. (Matthijs) Berends ac22b8d5c1 (v1.4.0.9038) docu update 2020-12-13 13:44:04 +01:00
dr. M.S. (Matthijs) Berends c8bcecf232 (v1.4.0.9037) random_* functions 2020-12-12 23:17:29 +01:00
dr. M.S. (Matthijs) Berends 2edd3339db (v1.4.0.9036) more unit tests 2020-12-11 12:17:23 +01:00
dr. M.S. (Matthijs) Berends 23ddc6004b (v1.4.0.9035) eucast_rules fix 2020-12-11 09:05:03 +01:00
dr. M.S. (Matthijs) Berends c9fc7e8a45 (v1.4.0.9034) MIC printing update 2020-12-09 09:40:50 +01:00
dr. M.S. (Matthijs) Berends 2145f1d1ba (v1.4.0.9033) documentation update 2020-12-08 12:37:25 +01:00
dr. M.S. (Matthijs) Berends 1bdb136b3a (v1.4.0.9032) auto-data guessing for functions 2020-12-07 16:06:42 +01:00
dr. M.S. (Matthijs) Berends fdf29e6c5b (v1.4.0.9031) as.ab() fix 2020-12-03 22:30:14 +01:00
dr. M.S. (Matthijs) Berends e03b3c96d3 (v1.4.0.9030) as.mo() fix for known lab codes 2020-12-03 16:59:04 +01:00
dr. M.S. (Matthijs) Berends 4c114ff4b4 (v1.4.0.9029) grey background for backticks, like readr pkg 2020-12-01 16:59:57 +01:00
dr. M.S. (Matthijs) Berends 00447c6dc4 git update 2020-11-28 22:15:44 +01:00
dr. M.S. (Matthijs) Berends 0e1fdb7dd7 (v1.4.0.9027) docu update 2020-11-25 20:26:02 +01:00
dr. M.S. (Matthijs) Berends 7b42b15c90 (v1.4.0.9026) docu update 2020-11-24 11:47:54 +01:00
dr. M.S. (Matthijs) Berends b045b571a6 (v1.4.0.9025) is_new_episode() 2020-11-23 21:50:27 +01:00
dr. M.S. (Matthijs) Berends 363218da7e (v1.4.0.9024) is_new_episode() 2020-11-17 16:57:41 +01:00
dr. M.S. (Matthijs) Berends 0800d33228 (v1.4.0.9023) unit tests 2020-11-17 11:53:56 +01:00
dr. M.S. (Matthijs) Berends 93428415d0 (v1.4.0.9022) small bugfix 2020-11-16 20:02:20 +01:00
dr. M.S. (Matthijs) Berends deefce9520 (v1.4.0.9021) more robust class setting 2020-11-16 16:57:55 +01:00
dr. M.S. (Matthijs) Berends 05fb213a7c (v1.4.0.9020) mo_is_intrinsic_resistant 2020-11-16 11:03:24 +01:00
dr. M.S. (Matthijs) Berends 9666b78ea7 (v1.4.0.9019) documentation update 2020-11-12 11:07:23 +01:00
dr. M.S. (Matthijs) Berends f2edac3b67 (v1.4.0.9018) reference_data in as.rsi() 2020-11-11 18:54:03 +01:00
dr. M.S. (Matthijs) Berends 01d9522434 (v1.4.0.9017) stringsAsFactors definitions 2020-11-11 16:49:27 +01:00
dr. M.S. (Matthijs) Berends 68ac39aa7f (v1.4.0.9016) as.rsi() older R versions 2020-11-10 19:59:14 +01:00
dr. M.S. (Matthijs) Berends 15c732703d (v1.4.0.9015) bugfix 2020-11-10 16:35:56 +01:00
dr. M.S. (Matthijs) Berends dd5a0319ef (v1.4.0.9014) bugfix 2020-11-09 15:18:36 +01:00
dr. M.S. (Matthijs) Berends d3b1d33210 (v1.4.0.9013) is_gram_negative/positive update 2020-11-09 13:07:02 +01:00
dr. M.S. (Matthijs) Berends 423879c034 (v1.4.0.9012) reference_df fix 2020-11-05 01:11:49 +01:00
dr. M.S. (Matthijs) Berends 5a607abb36 (v1.4.0.9011) message formatting 2020-10-27 15:56:51 +01:00
dr. M.S. (Matthijs) Berends 98773aa859 (v1.4.0.9010) GH actions update 2020-10-26 15:56:15 +01:00
dr. M.S. (Matthijs) Berends 3d096d96c2 (v1.4.0.9009) bugfix for older R version 2020-10-26 15:53:31 +01:00
dr. M.S. (Matthijs) Berends 760d69a3e0 (v1.4.0.9008) like variations 2020-10-26 12:23:03 +01:00
dr. M.S. (Matthijs) Berends f720c9ba0b (v1.4.0.9007) bugfix 2020-10-21 15:28:48 +02:00
dr. M.S. (Matthijs) Berends 8f868388ce (v1.4.0.9006) bugfix 2020-10-21 14:40:00 +02:00
dr. M.S. (Matthijs) Berends 9109b9dd62 (v1.4.0.9005) bugfix 2020-10-21 13:07:23 +02:00
dr. M.S. (Matthijs) Berends ade9f8bafd (v1.4.0.9004) bugfix 2020-10-21 11:50:43 +02:00
dr. M.S. (Matthijs) Berends 2ef7dfc8a3 (v1.4.0.9003) CoNS update 2020-10-20 21:00:57 +02:00
dr. M.S. (Matthijs) Berends ddae8085e1 (v1.4.0.9002) bugfix 2020-10-19 20:44:45 +02:00
dr. M.S. (Matthijs) Berends 4e9ccb4435 (v1.4.0.9001) is_gram_positive(), is_gram_negative(), parameter hardening 2020-10-19 17:09:19 +02:00
dr. M.S. (Matthijs) Berends 833a1be36d (v1.4.0.9000) more extensive unit tests 2020-10-15 09:46:41 +02:00
344 changed files with 18680 additions and 9261 deletions
+1 -1
View File
@@ -21,10 +21,10 @@
^public$
^data-raw$
^\.lintr$
^tests/testthat/_snaps$
^vignettes/AMR.Rmd$
^vignettes/benchmarks.Rmd$
^vignettes/EUCAST.Rmd$
^vignettes/MDR.Rmd$
^vignettes/PCA.Rmd$
^vignettes/resistance_predict.Rmd$
^vignettes/SPSS.Rmd$
+76 -31
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
on:
@@ -41,31 +41,50 @@ name: R-code-check
jobs:
R-code-check:
runs-on: ${{ matrix.config.os }}
continue-on-error: ${{ matrix.config.allowfail }}
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
name: ${{ matrix.config.os }} (R-${{ matrix.config.r }})
strategy:
fail-fast: false
matrix:
config:
- {os: windows-latest, r: 'release'}
- {os: macOS-latest, r: 'release'}
- {os: ubuntu-16.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
# - {os: windows-latest, r: 'oldrel'}
# - {os: macOS-latest, r: 'oldrel'}
# - {os: ubuntu-16.04, r: 'oldrel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: windows-latest, r: 'devel'}
# - {os: macOS-latest, r: 'devel'}
# - {os: ubuntu-16.04, r: '4.0', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
# - {os: windows-latest, r: '3.6'}
# - {os: ubuntu-16.04, r: '3.5', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
# - {os: ubuntu-16.04, r: '3.4', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
# - {os: ubuntu-16.04, r: '3.3', rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: macOS-latest, r: 'devel', allowfail: false}
- {os: macOS-latest, r: 'release', allowfail: false}
- {os: macOS-latest, r: 'oldrel', allowfail: false}
- {os: windows-latest, r: 'devel', allowfail: false}
- {os: windows-latest, r: 'release', allowfail: false}
- {os: windows-latest, r: 'oldrel', allowfail: false}
- {os: ubuntu-20.04, r: 'devel', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: ubuntu-20.04, r: 'release', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: ubuntu-20.04, r: 'oldrel', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: ubuntu-20.04, r: '4.0', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: ubuntu-20.04, r: '3.6', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: ubuntu-20.04, r: '3.5', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: ubuntu-20.04, r: '3.4', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: ubuntu-20.04, r: '3.3', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
# - {os: ubuntu-20.04, r: '3.2', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
# - {os: ubuntu-20.04, r: '3.1', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: ubuntu-20.04, r: '3.0', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"}
- {os: ubuntu-16.04, r: 'devel', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: 'release', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: 'oldrel', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '4.0', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.6', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.5', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.4', allowfail: false, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.3', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
# - {os: ubuntu-16.04, r: '3.2', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
# - {os: ubuntu-16.04, r: '3.1', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
- {os: ubuntu-16.04, r: '3.0', allowfail: true, rspm: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest"}
env:
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
RSPM: ${{ matrix.config.rspm }}
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v2
@@ -77,30 +96,45 @@ jobs:
- uses: r-lib/actions/setup-pandoc@master
- name: Query dependencies
if: matrix.config.r != '3.0' && matrix.config.r != '3.1' && matrix.config.r != '3.2'
run: |
install.packages('remotes')
saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
shell: Rscript {0}
- name: Cache R packages
if: runner.os != 'Windows'
if: runner.os != 'Windows' && matrix.config.r != '3.0' && matrix.config.r != '3.1' && matrix.config.r != '3.2'
uses: actions/cache@v1
with:
path: ${{ env.R_LIBS_USER }}
key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-
key: ${{ matrix.config.os }}-r-${{ matrix.config.r }}-3-${{ hashFiles('.github/depends.Rds') }}
restore-keys: ${{ matrix.config.os }}-r-${{ matrix.config.r }}-3-
- name: Install system dependencies
if: runner.os == 'Linux'
- name: Install Linux dependencies
if: runner.os == 'Linux' && matrix.config.r != '3.0' && matrix.config.r != '3.1' && matrix.config.r != '3.2'
env:
RHUB_PLATFORM: linux-x86_64-ubuntu-gcc
run: |
Rscript -e "remotes::install_github('r-hub/sysreqs')"
sysreqs=$(Rscript -e "cat(sysreqs::sysreq_commands('DESCRIPTION'))")
sudo -s eval "$sysreqs"
- name: Install Linux dependencies on old R versions
if: matrix.config.r == '3.0' || matrix.config.r == '3.1' || matrix.config.r == '3.2'
env:
RHUB_PLATFORM: linux-x86_64-ubuntu-gcc
# update the below with sysreqs::sysreqs("DESCRIPTION") and check the "DEB" entries (for Ubuntu).
# we don't want to depend on the sysreqs pkg here, as it requires a quite new R version
run: |
sudo apt install -y libssl-dev pandoc pandoc-citeproc libxml2-dev libicu-dev libcurl4-openssl-dev
- name: Install dependencies
- name: Install macOS dependencies
if: matrix.config.os == 'macOS-latest' && matrix.config.r == 'devel'
run: |
brew install mariadb-connector-c
- name: Install package dependencies
if: matrix.config.r != '3.0' && matrix.config.r != '3.1' && matrix.config.r != '3.2'
run: |
remotes::install_deps(dependencies = TRUE)
remotes::install_cran("rcmdcheck")
@@ -109,15 +143,26 @@ jobs:
- name: Session info
run: |
options(width = 100)
pkgs <- installed.packages()[, "Package"]
sessioninfo::session_info(pkgs, include_base = TRUE)
utils::sessionInfo()
as.data.frame(utils::installed.packages())[, "Version", drop = FALSE]
shell: Rscript {0}
- name: Check
- name: Run R CMD check
if: matrix.config.r != '3.0' && matrix.config.r != '3.1' && matrix.config.r != '3.2'
env:
_R_CHECK_CRAN_INCOMING_: false
run: rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check")
shell: Rscript {0}
- name: Run R CMD check on older R versions
if: matrix.config.r == '3.0' || matrix.config.r == '3.1' || matrix.config.r == '3.2'
env:
_R_CHECK_CRAN_INCOMING_: false
_R_CHECK_FORCE_SUGGESTS_: false
_R_CHECK_LENGTH_1_CONDITION_: verbose
_R_CHECK_LENGTH_1_LOGIC2_: verbose
run: |
R CMD check data-raw/AMR_latest.tar.gz --no-manual --no-build-vignettes
- name: Show testthat output
if: always()
@@ -126,7 +171,7 @@ jobs:
- name: Upload check results
if: failure()
uses: actions/upload-artifact@main
uses: actions/upload-artifact@master
with:
name: ${{ runner.os }}-r${{ matrix.config.r }}-results
name: ${{ matrix.config.os }}-r${{ matrix.config.r }}-results
path: check
+6 -6
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
on:
@@ -31,10 +31,10 @@ on:
branches:
- master
name: code-tested
name: code-coverage
jobs:
code-tested:
code-coverage:
runs-on: macOS-latest
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
@@ -67,5 +67,5 @@ jobs:
shell: Rscript {0}
- name: Test coverage
run: covr::codecov(line_exclusions = list("R/atc_online.R", "R/mo_source.R", "R/resistance_predict.R", "R/aa_helper_functions.R", "R/aa_helper_pm_functions.R", "R/zzz.R"), quiet = FALSE)
run: covr::codecov(line_exclusions = list("R/atc_online.R", "R/mo_source.R", "R/translate.R", "R/resistance_predict.R", "R/aa_helper_functions.R", "R/aa_helper_pm_functions.R", "R/zzz.R"), quiet = FALSE)
shell: Rscript {0}
+4 -4
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
on:
@@ -66,5 +66,5 @@ jobs:
shell: Rscript {0}
- name: Lint
run: lintr::lint_package(linters = lintr::with_defaults(line_length_linter = NULL, trailing_whitespace_linter = NULL, object_name_linter = NULL, cyclocomp_linter = NULL, object_usage_linter = NULL, object_length_linter = lintr::object_length_linter(length = 50L)), exclusions = list("R/aa_helper_pm_functions.R"))
run: lintr::lint_package(linters = lintr::with_defaults(line_length_linter = NULL, trailing_whitespace_linter = NULL, object_name_linter = NULL, cyclocomp_linter = NULL, object_length_linter = lintr::object_length_linter(length = 50L)), exclusions = list("R/aa_helper_pm_functions.R"))
shell: Rscript {0}
+6 -3
View File
@@ -1,7 +1,7 @@
Package: AMR
Version: 1.4.0
Date: 2020-10-08
Title: Antimicrobial Resistance Analysis
Version: 1.5.0.9023
Date: 2021-02-21
Title: Antimicrobial Resistance Data Analysis
Authors@R: c(
person(role = c("aut", "cre"),
family = "Berends", given = c("Matthijs", "S."), email = "m.s.berends@umcg.nl", comment = c(ORCID = "0000-0001-7620-1800")),
@@ -29,6 +29,8 @@ Authors@R: c(
family = "Meijer", given = c("Bart", "C."), email = "b.meijerg@certe.nl"),
person(role = "ctb",
family = "Ny", given = "Sofia", email = "sofia.ny@folkhalsomyndigheten.se"),
person(role = "ctb",
family = "Schade", given = c("Rogier", "P."), email = "r.schade@amsterdamumc.nl"),
person(role = "ctb",
family = "Souverein", given = "Dennis", email = "d.souvereing@streeklabhaarlem.nl"),
person(role = "ctb",
@@ -47,6 +49,7 @@ Suggests:
ggplot2,
knitr,
microbenchmark,
pillar,
readxl,
rmarkdown,
rstudioapi,
+26
View File
@@ -2,22 +2,27 @@
S3method("[",ab)
S3method("[",disk)
S3method("[",isolate_identifier)
S3method("[",mic)
S3method("[",mo)
S3method("[<-",ab)
S3method("[<-",disk)
S3method("[<-",isolate_identifier)
S3method("[<-",mic)
S3method("[<-",mo)
S3method("[<-",rsi)
S3method("[[",ab)
S3method("[[",disk)
S3method("[[",isolate_identifier)
S3method("[[",mic)
S3method("[[",mo)
S3method("[[<-",ab)
S3method("[[<-",disk)
S3method("[[<-",isolate_identifier)
S3method("[[<-",mic)
S3method("[[<-",mo)
S3method("[[<-",rsi)
S3method(all.equal,isolate_identifier)
S3method(as.data.frame,ab)
S3method(as.data.frame,mo)
S3method(as.double,mic)
@@ -31,6 +36,7 @@ S3method(barplot,mic)
S3method(barplot,rsi)
S3method(c,ab)
S3method(c,disk)
S3method(c,isolate_identifier)
S3method(c,mic)
S3method(c,mo)
S3method(c,rsi)
@@ -40,26 +46,32 @@ S3method(format,bug_drug_combinations)
S3method(kurtosis,data.frame)
S3method(kurtosis,default)
S3method(kurtosis,matrix)
S3method(plot,disk)
S3method(plot,mic)
S3method(plot,resistance_predict)
S3method(plot,rsi)
S3method(print,ab)
S3method(print,bug_drug_combinations)
S3method(print,catalogue_of_life_version)
S3method(print,custom_mdro_guideline)
S3method(print,disk)
S3method(print,isolate_identifier)
S3method(print,mic)
S3method(print,mo)
S3method(print,mo_renamed)
S3method(print,mo_uncertainties)
S3method(print,pca)
S3method(print,rsi)
S3method(skewness,data.frame)
S3method(skewness,default)
S3method(skewness,matrix)
S3method(summary,mic)
S3method(summary,mo)
S3method(summary,pca)
S3method(summary,rsi)
S3method(unique,ab)
S3method(unique,disk)
S3method(unique,isolate_identifier)
S3method(unique,mic)
S3method(unique,mo)
S3method(unique,rsi)
@@ -112,6 +124,8 @@ export(count_all)
export(count_df)
export(count_resistant)
export(count_susceptible)
export(custom_mdro_guideline)
export(eucast_dosage)
export(eucast_exceptional_phenotypes)
export(eucast_rules)
export(facet_rsi)
@@ -129,6 +143,7 @@ export(filter_first_weighted_isolate)
export(filter_fluoroquinolones)
export(filter_glycopeptides)
export(filter_macrolides)
export(filter_oxazolidinones)
export(filter_penicillins)
export(filter_tetracyclines)
export(first_isolate)
@@ -136,6 +151,7 @@ export(fluoroquinolones)
export(full_join_microorganisms)
export(g.test)
export(geom_rsi)
export(get_episode)
export(get_locale)
export(get_mo_source)
export(ggplot_pca)
@@ -150,6 +166,8 @@ export(is.mic)
export(is.mo)
export(is.rsi)
export(is.rsi.eligible)
export(is_new_episode)
export(isolate_identifier)
export(key_antibiotics)
export(key_antibiotics_equal)
export(kurtosis)
@@ -169,6 +187,10 @@ export(mo_fullname)
export(mo_genus)
export(mo_gramstain)
export(mo_info)
export(mo_is_gram_negative)
export(mo_is_gram_positive)
export(mo_is_intrinsic_resistant)
export(mo_is_yeast)
export(mo_kingdom)
export(mo_matching_score)
export(mo_name)
@@ -190,6 +212,7 @@ export(mo_url)
export(mo_year)
export(mrgn)
export(n_rsi)
export(oxazolidinones)
export(p_symbol)
export(pca)
export(penicillins)
@@ -199,6 +222,9 @@ export(proportion_R)
export(proportion_S)
export(proportion_SI)
export(proportion_df)
export(random_disk)
export(random_mic)
export(random_rsi)
export(resistance)
export(resistance_predict)
export(right_join_microorganisms)
+198 -55
View File
@@ -1,14 +1,157 @@
# AMR 1.4.0
Note: some changes in this version were suggested by anonymous reviewers from the journal we submitted our manuscipt about this package to. We are those reviewers very grateful for going through our code so thoroughly!
# AMR 1.5.0.9023
## <small>Last updated: 21 February 2021</small>
### New
* Support for 'EUCAST Expert Rules' / 'EUCAST Intrinsic Resistance and Unusual Phenotypes' version 3.2 of May 2020. With this addition to the previously implemented version 3.1 of 2016, the `eucast_rules()` function can now correct for more than 180 different antibiotics and the `mdro()` function can determine multidrug resistance based on more than 150 different antibiotics. All previously implemented versions of the EUCAST rules are now maintained and kept available in this package. The `eucast_rules()` function consequently gained the parameters `version_breakpoints` (at the moment defaults to v10.0, 2020) and `version_expertrules` (at the moment defaults to v3.2, 2020). The `example_isolates` data set now also reflects the change from v3.1 to v3.2. The `mdro()` function now accepts `guideline == "EUCAST3.1"` and `guideline == "EUCAST3.2"`.
* Support for EUCAST Clinical Breakpoints v11.0 (2021), effective in the `eucast_rules()` function and in `as.rsi()` to interpret MIC and disk diffusion values. This is now the default guideline in this package.
* Added function `eucast_dosage()` to get a `data.frame` with advised dosages of a certain bug-drug combination, which is based on the new `dosage` data set
* Added data set `dosage` to fuel the new `eucast_dosage()` function and to make this data available in a structured way
* Existing data set `example_isolates` now reflects the latest EUCAST rules
* Added argument `only_rsi_columns` for some functions, which defaults to `FALSE`, to indicate if the functions must only be applied to columns that are of class `<rsi>` (i.e., transformed with `as.rsi()`). This increases speed since automatic determination of antibiotic columns is not needed anymore. Affected functions are:
* All antibiotic selector functions (`ab_class()` and its wrappers, such as `aminoglycosides()`, `carbapenems()`, `penicillins()`)
* All antibiotic filter functions (`filter_ab_class()` and its wrappers, such as `filter_aminoglycosides()`, `filter_carbapenems()`, `filter_penicillins()`)
* `eucast_rules()`
* `mdro()` (including wrappers such as `brmo()`, `mrgn()` and `eucast_exceptional_phenotypes()`)
* `guess_ab_col()`
* Functions `oxazolidinones()` (an antibiotic selector function) and `filter_oxazolidinones()` (an antibiotic filter function) to select/filter on e.g. linezolid and tedizolid
```r
library(dplyr)
x <- example_isolates %>% select(date, hospital_id, oxazolidinones())
#> Selecting oxazolidinones: column 'LNZ' (linezolid)
x <- example_isolates %>% filter_oxazolidinones()
#> Filtering on oxazolidinones: value in column `LNZ` (linezolid) is either "R", "S" or "I"
```
* Support for custom MDRO guidelines, using the new `custom_mdro_guideline()` function, please see `mdro()` for additional info
* Function `isolate_identifier()`, which will paste a microorganism code with all antimicrobial results of a data set into one string for each row. This is useful to compare isolates, e.g. between institutions or regions, when there is no genotyping available.
* Function `mo_is_yeast()`, which determines whether a microorganism is a member of the taxonomic class Saccharomycetes or the taxonomic order Saccharomycetales:
```r
mo_kingdom(c("Aspergillus", "Candida"))
#> [1] "Fungi" "Fungi"
mo_is_yeast(c("Aspergillus", "Candida"))
#> [1] FALSE TRUE
# usage for filtering data:
example_isolates[which(mo_is_yeast()), ] # base R
example_isolates %>% filter(mo_is_yeast()) # dplyr
```
The `mo_type()` function has also been updated to reflect this change:
```r
mo_type(c("Aspergillus", "Candida"))
# [1] "Fungi" "Yeasts"
mo_type(c("Aspergillus", "Candida"), language = "es") # also supported: de, nl, fr, it, pt
#> [1] "Hongos" "Levaduras"
```
### Changed
* `is.rsi()` and `is.rsi.eligible()` now return a vector of `TRUE`/`FALSE` when the input is a data set, by iterating over all columns
* Using functions without setting a data set (e.g., `mo_is_gram_negative()`, `mo_is_gram_positive()`, `mo_is_intrinsic_resistant()`, `first_isolate()`, `mdro()`) now work with `dplyr`s `group_by()` again
* `first_isolate()` can be used with `group_by()` (also when using a dot `.` as input for the data) and now returns the names of the groups
* Updated the data set `microorganisms.codes` (which contains popular LIS and WHONET codes for microorganisms) for some species of *Mycobacterium* that previously incorrectly returned *M. africanum*
* Added Pretomanid (PMD, J04AK08) to the `antibiotics` data set
* WHONET code `"PNV"` will now correctly be interpreted as `PHN`, the antibiotic code for phenoxymethylpenicillin ('peni V')
* Fix for verbose output of `mdro(..., verbose = TRUE)` for German guideline (3MGRN and 4MGRN) and Dutch guideline (BRMO, only *P. aeruginosa*)
* `is.rsi.eligible()` now detects if the column name resembles an antibiotic name or code and now returns `TRUE` immediately if the input contains any of the values "R", "S" or "I". This drastically improves speed, also for a lot of other functions that rely on automatic determination of antibiotic columns.
* Functions `get_episode()` and `is_new_episode()` now support less than a day as value for argument `episode_days` (e.g., to include one patient/test per hour)
* Argument `ampc_cephalosporin_resistance` in `eucast_rules()` now also applies to value "I" (not only "S")
* Updated colours of values R, S and I in tibble printing
* Functions `print()` and `summary()` on a Principal Components Analysis object (`pca()`) now print additional group info if the original data was grouped using `dplyr::group_by()`
* Improved speed and reliability of `guess_ab_col()`. As this also internally improves the reliability of `first_isolate()` and `mdro()`, this might have a slight impact on the results of those functions.
* Fix for `mo_name()` when used in other languages than English
* The `like()` function (and its fast alias `%like%`) now always use Perl compatibility, improving speed for many functions in this package (e.g., `as.mo()` is now up to 4 times faster)
* *Staphylococcus cornubiensis* is now correctly categorised as coagulase-positive
### Other
* Big documentation updates
* Loading the package (i.e., `library(AMR)`) now is ~50 times faster than before, in costs of package size (which increased by ~3 MB)
# AMR 1.5.0
### New
* Functions `get_episode()` and `is_new_episode()` to determine (patient) episodes which are not necessarily based on microorganisms. The `get_episode()` function returns the index number of the episode per group, while the `is_new_episode()` function returns values `TRUE`/`FALSE` to indicate whether an item in a vector is the start of a new episode. They also support `dplyr`s grouping (i.e. using `group_by()`):
```r
library(dplyr)
example_isolates %>%
group_by(patient_id, hospital_id) %>%
filter(is_new_episode(date, episode_days = 60))
```
* Functions `mo_is_gram_negative()` and `mo_is_gram_positive()` as wrappers around `mo_gramstain()`. They always return `TRUE` or `FALSE` (except when the input is `NA` or the MO code is `UNKNOWN`), thus always return `FALSE` for species outside the taxonomic kingdom of Bacteria.
* Function `mo_is_intrinsic_resistant()` to test for intrinsic resistance, based on [EUCAST Intrinsic Resistance and Unusual Phenotypes v3.2](https://www.eucast.org/expert_rules_and_intrinsic_resistance/) from 2020.
* Functions `random_mic()`, `random_disk()` and `random_rsi()` for random value generation. The functions `random_mic()` and `random_disk()` take microorganism names and antibiotic names as input to make generation more realistic.
### Changed
* New argument `ampc_cephalosporin_resistance` in `eucast_rules()` to correct for AmpC de-repressed cephalosporin-resistant mutants
* Interpretation of antimicrobial resistance - `as.rsi()`:
* Reference data used for `as.rsi()` can now be set by the user, using the `reference_data` argument. This allows for using own interpretation guidelines. The user-set data must have the same structure as `rsi_translation`.
* Better determination of disk zones and MIC values when running `as.rsi()` on a data.frame
* Fix for using `as.rsi()` on a data.frame in older R versions
* `as.rsi()` on a data.frame will not print a message anymore if the values are already clean R/SI values
* If using `as.rsi()` on MICs or disk diffusion while there is intrinsic antimicrobial resistance, a warning will be thrown to remind about this
* Fix for using `as.rsi()` on a `data.frame` that only contains one column for antibiotic interpretations
* Some functions are now context-aware when used inside `dplyr` verbs, such as `filter()`, `mutate()` and `summarise()`. This means that then the data argument does not need to be set anymore. This is the case for the new functions:
* `mo_is_gram_negative()`
* `mo_is_gram_positive()`
* `mo_is_intrinsic_resistant()`
... and for the existing functions:
* `first_isolate()`,
* `key_antibiotics()`,
* `mdro()`,
* `brmo()`,
* `mrgn()`,
* `mdr_tb()`,
* `mdr_cmi2012()`,
* `eucast_exceptional_phenotypes()`
```r
# to select first isolates that are Gram-negative
# and view results of cephalosporins and aminoglycosides:
library(dplyr)
example_isolates %>%
filter(first_isolate(), mo_is_gram_negative()) %>%
select(mo, cephalosporins(), aminoglycosides()) %>%
as_tibble()
```
* For antibiotic selection functions (such as `cephalosporins()`, `aminoglycosides()`) to select columns based on a certain antibiotic group, the dependency on the `tidyselect` package was removed, meaning that they can now also be used without the need to have this package installed and now also work in base R function calls (they rely on R 3.2 or later):
```r
# above example in base R:
example_isolates[which(first_isolate() & mo_is_gram_negative()),
c("mo", cephalosporins(), aminoglycosides())]
```
* For all function arguments in the code, it is now defined what the exact type of user input should be (inspired by the [`typed`](https://github.com/moodymudskipper/typed) package). If the user input for a certain function does not meet the requirements for a specific argument (such as the class or length), an informative error will be thrown. This makes the package more robust and the use of it more reproducible and reliable. In total, more than 420 arguments were defined.
* Fix for `set_mo_source()`, that previously would not remember the file location of the original file
* Deprecated function `p_symbol()` that not really fits the scope of this package. It will be removed in a future version. See [here](https://github.com/msberends/AMR/blob/v1.4.0/R/p_symbol.R) for the source code to preserve it.
* Updated coagulase-negative staphylococci determination with Becker *et al.* 2020 (PMID 32056452), meaning that the species *S. argensis*, *S. caeli*, *S. debuckii*, *S. edaphicus* and *S. pseudoxylosus* are now all considered CoNS
* Fix for using argument `reference_df` in `as.mo()` and `mo_*()` functions that contain old microbial codes (from previous package versions)
* Fixed a bug where `mo_uncertainties()` would not return the results based on the MO matching score
* Fixed a bug where `as.mo()` would not return results for known laboratory codes for microorganisms
* Fixed a bug where `as.ab()` would sometimes fail
* Better tibble printing for MIC values
* Fix for plotting MIC values with `plot()`
* Added `plot()` generic to class `<disk>`
* LA-MRSA and CA-MRSA are now recognised as an abbreviation for *Staphylococcus aureus*, meaning that e.g. `mo_genus("LA-MRSA")` will return `"Staphylococcus"` and `mo_is_gram_positive("LA-MRSA")` will return `TRUE`.
* Fix for printing class <mo> in tibbles when all values are `NA`
* Fix for `mo_shortname()` when the input contains `NA`
* If `as.mo()` takes more than 30 seconds, some suggestions will be done to improve speed
### Other
* All messages and warnings thrown by this package now break sentences on whole words
* More extensive unit tests
* Internal calls to `options()` were all removed in favour of a new internal environment `pkg_env`
* Improved internal type setting (among other things: replaced all `sapply()` calls with `vapply()`)
* Added CodeFactor as a continuous code review to this package: <https://www.codefactor.io/repository/github/msberends/amr/>
* Added Dr. Rogier Schade as contributor
# AMR 1.4.0
### New
* Support for 'EUCAST Expert Rules' / 'EUCAST Intrinsic Resistance and Unusual Phenotypes' version 3.2 of May 2020. With this addition to the previously implemented version 3.1 of 2016, the `eucast_rules()` function can now correct for more than 180 different antibiotics and the `mdro()` function can determine multidrug resistance based on more than 150 different antibiotics. All previously implemented versions of the EUCAST rules are now maintained and kept available in this package. The `eucast_rules()` function consequently gained the arguments `version_breakpoints` (at the moment defaults to v10.0, 2020) and `version_expertrules` (at the moment defaults to v3.2, 2020). The `example_isolates` data set now also reflects the change from v3.1 to v3.2. The `mdro()` function now accepts `guideline == "EUCAST3.1"` and `guideline == "EUCAST3.2"`.
* A new vignette and website page with info about all our public and freely available data sets, that can be downloaded as flat files or in formats for use in R, SPSS, SAS, Stata and Excel: https://msberends.github.io/AMR/articles/datasets.html
* Data set `intrinsic_resistant`. This data set contains all bug-drug combinations where the 'bug' is intrinsic resistant to the 'drug' according to the latest EUCAST insights. It contains just two columns: `microorganism` and `antibiotic`.
Curious about which enterococci are actually intrinsic resistant to vancomycin?
```r
library(AMR)
library(dplyr)
@@ -35,7 +178,7 @@ Note: some changes in this version were suggested by anonymous reviewers from th
```
* Cleaning columns in a data.frame now allows you to specify those columns with tidy selection, e.g. `as.rsi(df, col1:col9)`
* Big speed improvement for interpreting MIC values and disk zone diameters. When interpreting 5,000 MIC values of two antibiotics (10,000 values in total), our benchmarks showed a total run time going from 80.7-85.1 seconds to 1.8-2.0 seconds.
* Added parameter 'add_intrinsic_resistance' (defaults to `FALSE`), that considers intrinsic resistance according to EUCAST
* Added argument 'add_intrinsic_resistance' (defaults to `FALSE`), that considers intrinsic resistance according to EUCAST
* Fixed a bug where in EUCAST rules the breakpoint for R would be interpreted as ">=" while this should have been "<"
* Added intelligent data cleaning to `as.disk()`, so numbers can also be extracted from text and decimal numbers will always be rounded up:
```r
@@ -46,7 +189,7 @@ Note: some changes in this version were suggested by anonymous reviewers from th
* Improvements for `as.mo()`:
* A completely new matching score for ambiguous user input, using `mo_matching_score()`. Any user input value that could mean more than one taxonomic entry is now considered 'uncertain'. Instead of a warning, a message will be thrown and the accompanying `mo_uncertainties()` has been changed completely; it now prints all possible candidates with their matching score.
* Big speed improvement for already valid microorganism ID. This also means an significant speed improvement for using `mo_*` functions like `mo_name()` on microoganism IDs.
* Added parameter `ignore_pattern` to `as.mo()` which can also be given to `mo_*` functions like `mo_name()`, to exclude known non-relevant input from analysing. This can also be set with the option `AMR_ignore_pattern`.
* Added argument `ignore_pattern` to `as.mo()` which can also be given to `mo_*` functions like `mo_name()`, to exclude known non-relevant input from analysing. This can also be set with the option `AMR_ignore_pattern`.
* `get_locale()` now uses at default `Sys.getenv("LANG")` or, if `LANG` is not set, `Sys.getlocale()`. This can be overwritten by setting the option `AMR_locale`.
* Big speed improvement for `eucast_rules()`
* Overall speed improvement by tweaking joining functions
@@ -57,7 +200,7 @@ Note: some changes in this version were suggested by anonymous reviewers from th
* Updated the documentation of the `WHONET` data set to clarify that all patient names are fictitious
* Small `as.ab()` algorithm improvements
* Fix for combining MIC values with raw numbers, i.e. `c(as.mic(2), 2)` previously failed but now returns a valid MIC class
* `ggplot_rsi()` and `geom_rsi()` gained parameters `minimum` and `language`, to influence the internal use of `rsi_df()`
* `ggplot_rsi()` and `geom_rsi()` gained arguments `minimum` and `language`, to influence the internal use of `rsi_df()`
* Changes in the `antibiotics` data set:
* Updated oral and parental DDDs from the WHOCC
* Added abbreviation "piptazo" to 'Piperacillin/tazobactam' (TZP)
@@ -65,7 +208,7 @@ Note: some changes in this version were suggested by anonymous reviewers from th
* 'Penicillin V' (for oral use, code `PNV`) was removed, since its actual entry 'Phenoxymethylpenicillin' (code `PHN`) already existed
* The group name (`antibiotics$group`) of 'Linezolid' (`LNZ`), 'Cycloserine' (`CYC`), 'Tedizolid' (`TZD`) and 'Thiacetazone' (`THA`) is now "Oxazolidinones" instead of "Other antibacterials"
* Added support for using `unique()` on classes `<rsi>`, `<mic>`, `<disk>`, `<ab>` and `<mo>`
* Added parameter `excess` to the `kurtosis()` function (defaults to `FALSE`), to return the *excess kurtosis*, defined as the kurtosis minus three.
* Added argument `excess` to the `kurtosis()` function (defaults to `FALSE`), to return the *excess kurtosis*, defined as the kurtosis minus three.
### Other
* Removed functions `portion_R()`, `portion_S()` and `portion_I()` that were deprecated since version 0.9.0 (November 2019) and were replaced with `proportion_R()`, `proportion_S()` and `proportion_I()`
@@ -90,7 +233,7 @@ Note: some changes in this version were suggested by anonymous reviewers from th
* Added official antimicrobial names to all `filter_ab_class()` functions, such as `filter_aminoglycosides()`
* Added antibiotics code "FOX1" for cefoxitin screening (abbreviation "cfsc") to the `antibiotics` data set
* Added Monuril as trade name for fosfomycin
* Added parameter `conserve_capped_values` to `as.rsi()` for interpreting MIC values - it makes sure that values starting with "<" (but not "<=") will always return "S" and values starting with ">" (but not ">=") will always return "R". The default behaviour of `as.rsi()` has not changed, so you need to specifically do `as.rsi(..., conserve_capped_values = TRUE)`.
* Added argument `conserve_capped_values` to `as.rsi()` for interpreting MIC values - it makes sure that values starting with "<" (but not "<=") will always return "S" and values starting with ">" (but not ">=") will always return "R". The default behaviour of `as.rsi()` has not changed, so you need to specifically do `as.rsi(..., conserve_capped_values = TRUE)`.
### Changed
* Big speed improvement for using any function on microorganism codes from earlier package versions (prior to `AMR` v1.2.0), such as `as.mo()`, `mo_name()`, `first_isolate()`, `eucast_rules()`, `mdro()`, etc.
@@ -198,7 +341,7 @@ Note: some changes in this version were suggested by anonymous reviewers from th
mutate_at(vars(antibiotic1:antibiotic25), as.rsi, mo = .$mybacteria)
```
* Added antibiotic abbreviations for a laboratory manufacturer (GLIMS) for cefuroxime, cefotaxime, ceftazidime, cefepime, cefoxitin and trimethoprim/sulfamethoxazole
* Added `uti` (as abbreviation of urinary tract infections) as parameter to `as.rsi()`, so interpretation of MIC values and disk zones can be made dependent on isolates specifically from UTIs
* Added `uti` (as abbreviation of urinary tract infections) as argument to `as.rsi()`, so interpretation of MIC values and disk zones can be made dependent on isolates specifically from UTIs
* Info printing in functions `eucast_rules()`, `first_isolate()`, `mdro()` and `resistance_predict()` will now at default only print when R is in an interactive mode (i.e. not in RMarkdown)
# AMR 1.0.0
@@ -318,7 +461,7 @@ This software is now out of beta and considered stable. Nonetheless, this packag
# AMR 0.8.0
### Breaking
* Determination of first isolates now **excludes** all 'unknown' microorganisms at default, i.e. microbial code `"UNKNOWN"`. They can be included with the new parameter `include_unknown`:
* Determination of first isolates now **excludes** all 'unknown' microorganisms at default, i.e. microbial code `"UNKNOWN"`. They can be included with the new argument `include_unknown`:
```r
first_isolate(..., include_unknown = TRUE)
```
@@ -369,7 +512,7 @@ This software is now out of beta and considered stable. Nonetheless, this packag
```r
format(x, combine_IR = FALSE)
```
* Additional way to calculate co-resistance, i.e. when using multiple antimicrobials as input for `portion_*` functions or `count_*` functions. This can be used to determine the empiric susceptibility of a combination therapy. A new parameter `only_all_tested` (**which defaults to `FALSE`**) replaces the old `also_single_tested` and can be used to select one of the two methods to count isolates and calculate portions. The difference can be seen in this example table (which is also on the `portion` and `count` help pages), where the %SI is being determined:
* Additional way to calculate co-resistance, i.e. when using multiple antimicrobials as input for `portion_*` functions or `count_*` functions. This can be used to determine the empiric susceptibility of a combination therapy. A new argument `only_all_tested` (**which defaults to `FALSE`**) replaces the old `also_single_tested` and can be used to select one of the two methods to count isolates and calculate portions. The difference can be seen in this example table (which is also on the `portion` and `count` help pages), where the %SI is being determined:
```r
# --------------------------------------------------------------------
@@ -425,13 +568,13 @@ This software is now out of beta and considered stable. Nonetheless, this packag
* Removed deprecated functions `abname()`, `ab_official()`, `atc_name()`, `atc_official()`, `atc_property()`, `atc_tradenames()`, `atc_trivial_nl()`
* Fix and speed improvement for `mo_shortname()`
* Fix for using `mo_*` functions where the coercion uncertainties and failures would not be available through `mo_uncertainties()` and `mo_failures()` anymore
* Deprecated the `country` parameter of `mdro()` in favour of the already existing `guideline` parameter to support multiple guidelines within one country
* Deprecated the `country` argument of `mdro()` in favour of the already existing `guideline` argument to support multiple guidelines within one country
* The `name` of `RIF` is now Rifampicin instead of Rifampin
* The `antibiotics` data set is now sorted by name and all cephalosporins now have their generation between brackets
* Speed improvement for `guess_ab_col()` which is now 30 times faster for antibiotic abbreviations
* Improved `filter_ab_class()` to be more reliable and to support 5th generation cephalosporins
* Function `availability()` now uses `portion_R()` instead of `portion_IR()`, to comply with EUCAST insights
* Functions `age()` and `age_groups()` now have a `na.rm` parameter to remove empty values
* Functions `age()` and `age_groups()` now have a `na.rm` argument to remove empty values
* Renamed function `p.symbol()` to `p_symbol()` (the former is now deprecated and will be removed in a future version)
* Using negative values for `x` in `age_groups()` will now introduce `NA`s and not return an error anymore
* Fix for determining the system's language
@@ -526,12 +669,12 @@ This software is now out of beta and considered stable. Nonetheless, this packag
* All `atc_*` functions are superceded by `ab_*` functions
* All output will be translated by using an included translation file which [can be viewed here](https://github.com/msberends/AMR/blob/master/data-raw/translations.tsv)
* Improvements to plotting AMR results with `ggplot_rsi()`:
* New parameter `colours` to set the bar colours
* New parameters `title`, `subtitle`, `caption`, `x.title` and `y.title` to set titles and axis descriptions
* New argument `colours` to set the bar colours
* New arguments `title`, `subtitle`, `caption`, `x.title` and `y.title` to set titles and axis descriptions
* Improved intelligence of looking up antibiotic columns in a data set using `guess_ab_col()`
* Added ~5,000 more old taxonomic names to the `microorganisms.old` data set, which leads to better results finding when using the `as.mo()` function
* This package now honours the new EUCAST insight (2019) that S and I are but classified as susceptible, where I is defined as 'increased exposure' and not 'intermediate' anymore. For functions like `portion_df()` and `count_df()` this means that their new parameter `combine_SI` is TRUE at default. Our plotting function `ggplot_rsi()` also reflects this change since it uses `count_df()` internally.
* The `age()` function gained a new parameter `exact` to determine ages with decimals
* This package now honours the new EUCAST insight (2019) that S and I are but classified as susceptible, where I is defined as 'increased exposure' and not 'intermediate' anymore. For functions like `portion_df()` and `count_df()` this means that their new argument `combine_SI` is TRUE at default. Our plotting function `ggplot_rsi()` also reflects this change since it uses `count_df()` internally.
* The `age()` function gained a new argument `exact` to determine ages with decimals
* Removed deprecated functions `guess_mo()`, `guess_atc()`, `EUCAST_rules()`, `interpretive_reading()`, `rsi()`
* Frequency tables (`freq()`):
* speed improvement for microbial IDs
@@ -575,11 +718,11 @@ This software is now out of beta and considered stable. Nonetheless, this packag
We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.gitlab.io/AMR/) (built with the great [`pkgdown`](https://pkgdown.r-lib.org/))
* Contains the complete manual of this package and all of its functions with an explanation of their parameters
* Contains a comprehensive tutorial about how to conduct antimicrobial resistance analysis, import data from WHONET or SPSS and many more.
* Contains the complete manual of this package and all of its functions with an explanation of their arguments
* Contains a comprehensive tutorial about how to conduct AMR data analysis, import data from WHONET or SPSS and many more.
#### New
* **BREAKING**: removed deprecated functions, parameters and references to 'bactid'. Use `as.mo()` to identify an MO code.
* **BREAKING**: removed deprecated functions, arguments and references to 'bactid'. Use `as.mo()` to identify an MO code.
* Catalogue of Life as a new taxonomic source for data about microorganisms, which also contains all ITIS data we used previously. The `microorganisms` data set now contains:
* All ~55,000 (sub)species from the kingdoms of Archaea, Bacteria and Protozoa
* All ~3,000 (sub)species from these orders of the kingdom of Fungi: Eurotiales, Onygenales, Pneumocystales, Saccharomycetales and Schizosaccharomycetales (covering at least like all species of *Aspergillus*, *Candida*, *Pneumocystis*, *Saccharomyces* and *Trichophyton*)
@@ -592,7 +735,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
* New function `mo_rank()` for the taxonomic rank (genus, species, infraspecies, etc.)
* New function `mo_url()` to get the direct URL of a species from the Catalogue of Life
* Support for data from [WHONET](https://whonet.org/) and [EARS-Net](https://www.ecdc.europa.eu/en/about-us/partnerships-and-networks/disease-and-laboratory-networks/ears-net) (European Antimicrobial Resistance Surveillance Network):
* Exported files from WHONET can be read and used in this package. For functions like `first_isolate()` and `eucast_rules()`, all parameters will be filled in automatically.
* Exported files from WHONET can be read and used in this package. For functions like `first_isolate()` and `eucast_rules()`, all arguments will be filled in automatically.
* This package now knows all antibiotic abbrevations by EARS-Net (which are also being used by WHONET) - the `antibiotics` data set now contains a column `ears_net`.
* The function `as.mo()` now knows all WHONET species abbreviations too, because almost 2,000 microbial abbreviations were added to the `microorganisms.codes` data set.
* New filters for antimicrobial classes. Use these functions to filter isolates on results in one of more antibiotics from a specific class:
@@ -635,7 +778,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
* New function `mo_uncertainties()` to review values that could be coerced to a valid MO code using `as.mo()`, but with uncertainty.
* New function `mo_renamed()` to get a list of all returned values from `as.mo()` that have had taxonomic renaming
* New function `age()` to calculate the (patients) age in years
* New function `age_groups()` to split ages into custom or predefined groups (like children or elderly). This allows for easier demographic antimicrobial resistance analysis per age group.
* New function `age_groups()` to split ages into custom or predefined groups (like children or elderly). This allows for easier demographic AMR data analysis per age group.
* New function `ggplot_rsi_predict()` as well as the base R `plot()` function can now be used for resistance prediction calculated with `resistance_predict()`:
```r
x <- resistance_predict(septic_patients, col_ab = "amox")
@@ -713,14 +856,14 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
* Console will return the percentage of uncoercable input
* Function `first_isolate()`:
* Fixed a bug where distances between dates would not be calculated right - in the `septic_patients` data set this yielded a difference of 0.15% more isolates
* Will now use a column named like "patid" for the patient ID (parameter `col_patientid`), when this parameter was left blank
* Will now use a column named like "key(...)ab" or "key(...)antibiotics" for the key antibiotics (parameter `col_keyantibiotics()`), when this parameter was left blank
* Removed parameter `output_logical`, the function will now always return a logical value
* Renamed parameter `filter_specimen` to `specimen_group`, although using `filter_specimen` will still work
* A note to the manual pages of the `portion` functions, that low counts can influence the outcome and that the `portion` functions may camouflage this, since they only return the portion (albeit being dependent on the `minimum` parameter)
* Will now use a column named like "patid" for the patient ID (argument `col_patientid`), when this argument was left blank
* Will now use a column named like "key(...)ab" or "key(...)antibiotics" for the key antibiotics (argument `col_keyantibiotics()`), when this argument was left blank
* Removed argument `output_logical`, the function will now always return a logical value
* Renamed argument `filter_specimen` to `specimen_group`, although using `filter_specimen` will still work
* A note to the manual pages of the `portion` functions, that low counts can influence the outcome and that the `portion` functions may camouflage this, since they only return the portion (albeit being dependent on the `minimum` argument)
* Merged data sets `microorganisms.certe` and `microorganisms.umcg` into `microorganisms.codes`
* Function `mo_taxonomy()` now contains the kingdom too
* Reduce false positives for `is.rsi.eligible()` using the new `threshold` parameter
* Reduce false positives for `is.rsi.eligible()` using the new `threshold` argument
* New colours for `scale_rsi_colours()`
* Summaries of class `mo` will now return the top 3 and the unique count, e.g. using `summary(mo)`
* Small text updates to summaries of class `rsi` and `mic`
@@ -745,16 +888,16 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
freq(mo_genus(mo))
```
* Header info is now available as a list, with the `header` function
* The parameter `header` is now set to `TRUE` at default, even for markdown
* The argument `header` is now set to `TRUE` at default, even for markdown
* Added header info for class `mo` to show unique count of families, genera and species
* Now honours the `decimal.mark` setting, which just like `format` defaults to `getOption("OutDec")`
* The new `big.mark` parameter will at default be `","` when `decimal.mark = "."` and `"."` otherwise
* The new `big.mark` argument will at default be `","` when `decimal.mark = "."` and `"."` otherwise
* Fix for header text where all observations are `NA`
* New parameter `droplevels` to exclude empty factor levels when input is a factor
* New argument `droplevels` to exclude empty factor levels when input is a factor
* Factor levels will be in header when present in input data (maximum of 5)
* Fix for using `select()` on frequency tables
* Function `scale_y_percent()` now contains the `limits` parameter
* Automatic parameter filling for `mdro()`, `key_antibiotics()` and `eucast_rules()`
* Function `scale_y_percent()` now contains the `limits` argument
* Automatic argument filling for `mdro()`, `key_antibiotics()` and `eucast_rules()`
* Updated examples for resistance prediction (`resistance_predict()` function)
* Fix for `as.mic()` to support more values ending in (several) zeroes
* if using different lengths of pattern and x in `%like%`, it will now return the call
@@ -767,7 +910,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
#### New
* Repository moved to GitLab
* Function `count_all` to get all available isolates (that like all `portion_*` and `count_*` functions also supports `summarise` and `group_by`), the old `n_rsi` is now an alias of `count_all`
* Function `get_locale` to determine language for language-dependent output for some `mo_*` functions. This is now the default value for their `language` parameter, by which the system language will be used at default.
* Function `get_locale` to determine language for language-dependent output for some `mo_*` functions. This is now the default value for their `language` argument, by which the system language will be used at default.
* Data sets `microorganismsDT`, `microorganisms.prevDT`, `microorganisms.unprevDT` and `microorganisms.oldDT` to improve the speed of `as.mo`. They are for reference only, since they are primarily for internal use of `as.mo`.
* Function `read.4D` to read from the 4D database of the MMB department of the UMCG
* Functions `mo_authors` and `mo_year` to get specific values about the scientific reference of a taxonomic entry
@@ -777,12 +920,12 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
* `EUCAST_rules` was renamed to `eucast_rules`, the old function still exists as a deprecated function
* Big changes to the `eucast_rules` function:
* Now also applies rules from the EUCAST 'Breakpoint tables for bacteria', version 8.1, 2018, https://www.eucast.org/clinical_breakpoints/ (see Source of the function)
* New parameter `rules` to specify which rules should be applied (expert rules, breakpoints, others or all)
* New parameter `verbose` which can be set to `TRUE` to get very specific messages about which columns and rows were affected
* New argument `rules` to specify which rules should be applied (expert rules, breakpoints, others or all)
* New argument `verbose` which can be set to `TRUE` to get very specific messages about which columns and rows were affected
* Better error handling when rules cannot be applied (i.e. new values could not be inserted)
* The number of affected values will now only be measured once per row/column combination
* Data set `septic_patients` now reflects these changes
* Added parameter `pipe` for piperacillin (J01CA12), also to the `mdro` function
* Added argument `pipe` for piperacillin (J01CA12), also to the `mdro` function
* Small fixes to EUCAST clinical breakpoint rules
* Added column `kingdom` to the microorganisms data set, and function `mo_kingdom` to look up values
* Tremendous speed improvement for `as.mo` (and subsequently all `mo_*` functions), as empty values wil be ignored *a priori*
@@ -794,10 +937,10 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
as.mo("S. spp") # B_STPHY
mo_fullname("S. species") # "Staphylococcus species"
```
* Added parameter `combine_IR` (TRUE/FALSE) to functions `portion_df` and `count_df`, to indicate that all values of I and R must be merged into one, so the output only consists of S vs. IR (susceptible vs. non-susceptible)
* Added argument `combine_IR` (TRUE/FALSE) to functions `portion_df` and `count_df`, to indicate that all values of I and R must be merged into one, so the output only consists of S vs. IR (susceptible vs. non-susceptible)
* Fix for `portion_*(..., as_percent = TRUE)` when minimal number of isolates would not be met
* Added parameter `also_single_tested` for `portion_*` and `count_*` functions to also include cases where not all antibiotics were tested but at least one of the tested antibiotics includes the target antimicribial interpretation, see `?portion`
* Using `portion_*` functions now throws a warning when total available isolate is below parameter `minimum`
* Added argument `also_single_tested` for `portion_*` and `count_*` functions to also include cases where not all antibiotics were tested but at least one of the tested antibiotics includes the target antimicribial interpretation, see `?portion`
* Using `portion_*` functions now throws a warning when total available isolate is below argument `minimum`
* Functions `as.mo`, `as.rsi`, `as.mic`, `as.atc` and `freq` will not set package name as attribute anymore
* Frequency tables - `freq()`:
* Support for grouping variables, test with:
@@ -816,17 +959,17 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
* Now prints in markdown at default in non-interactive sessions
* No longer adds the factor level column and sorts factors on count again
* Support for class `difftime`
* New parameter `na`, to choose which character to print for empty values
* New parameter `header` to turn the header info off (default when `markdown = TRUE`)
* New parameter `title` to manually setbthe title of the frequency table
* `first_isolate` now tries to find columns to use as input when parameters are left blank
* New argument `na`, to choose which character to print for empty values
* New argument `header` to turn the header info off (default when `markdown = TRUE`)
* New argument `title` to manually setbthe title of the frequency table
* `first_isolate` now tries to find columns to use as input when arguments are left blank
* Improvements for MDRO algorithm (function `mdro`)
* Data set `septic_patients` is now a `data.frame`, not a tibble anymore
* Removed diacritics from all authors (columns `microorganisms$ref` and `microorganisms.old$ref`) to comply with CRAN policy to only allow ASCII characters
* Fix for `mo_property` not working properly
* Fix for `eucast_rules` where some Streptococci would become ceftazidime R in EUCAST rule 4.5
* Support for named vectors of class `mo`, useful for `top_freq()`
* `ggplot_rsi` and `scale_y_percent` have `breaks` parameter
* `ggplot_rsi` and `scale_y_percent` have `breaks` argument
* AI improvements for `as.mo`:
* `"CRS"` -> *Stenotrophomonas maltophilia*
* `"CRSM"` -> *Stenotrophomonas maltophilia*
@@ -893,7 +1036,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
# min median max neval
# 0.01817717 0.01843957 0.03878077 100
```
* Added parameter `reference_df` for `as.mo`, so users can supply their own microbial IDs, name or codes as a reference table
* Added argument `reference_df` for `as.mo`, so users can supply their own microbial IDs, name or codes as a reference table
* Renamed all previous references to `bactid` to `mo`, like:
* Column names inputs of `EUCAST_rules`, `first_isolate` and `key_antibiotics`
* Column names of datasets `microorganisms` and `septic_patients`
@@ -922,7 +1065,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
* Fix for `as.mic` for values ending in zeroes after a real number
* Small fix where *B. fragilis* would not be found in the `microorganisms.umcg` data set
* Added `prevalence` column to the `microorganisms` data set
* Added parameters `minimum` and `as_percent` to `portion_df`
* Added arguments `minimum` and `as_percent` to `portion_df`
* Support for quasiquotation in the functions series `count_*` and `portions_*`, and `n_rsi`. This allows to check for more than 2 vectors or columns.
```r
septic_patients %>% select(amox, cipr) %>% count_IR()
@@ -933,12 +1076,12 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
septic_patients %>% portion_S(amcl, gent)
septic_patients %>% portion_S(amcl, gent, pita)
```
* Edited `ggplot_rsi` and `geom_rsi` so they can cope with `count_df`. The new `fun` parameter has value `portion_df` at default, but can be set to `count_df`.
* Edited `ggplot_rsi` and `geom_rsi` so they can cope with `count_df`. The new `fun` argument has value `portion_df` at default, but can be set to `count_df`.
* Fix for `ggplot_rsi` when the `ggplot2` package was not loaded
* Added datalabels function `labels_rsi_count` to `ggplot_rsi`
* Added possibility to set any parameter to `geom_rsi` (and `ggplot_rsi`) so you can set your own preferences
* Added possibility to set any argument to `geom_rsi` (and `ggplot_rsi`) so you can set your own preferences
* Fix for joins, where predefined suffices would not be honoured
* Added parameter `quote` to the `freq` function
* Added argument `quote` to the `freq` function
* Added generic function `diff` for frequency tables
* Added longest en shortest character length in the frequency table (`freq`) header of class `character`
* Support for types (classes) list and matrix for `freq`
@@ -995,7 +1138,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
#### Changed
* Improvements for forecasting with `resistance_predict` and added more examples
* More antibiotics added as parameters for EUCAST rules
* More antibiotics added as arguments for EUCAST rules
* Updated version of the `septic_patients` data set to better reflect the reality
* Pretty printing for tibbles removed as it is not really the scope of this package
* Printing of `mic` and `rsi` classes now returns all values - use `freq` to check distributions
@@ -1003,7 +1146,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
* Column names for the `key_antibiotics` function are now generic: 6 for broadspectrum ABs, 6 for Gram-positive specific and 6 for Gram-negative specific ABs
* Speed improvement for the `abname` function
* `%like%` now supports multiple patterns
* Frequency tables are now actual `data.frame`s with altered console printing to make it look like a frequency table. Because of this, the parameter `toConsole` is not longer needed.
* Frequency tables are now actual `data.frame`s with altered console printing to make it look like a frequency table. Because of this, the argument `toConsole` is not longer needed.
* Fix for `freq` where the class of an item would be lost
* Small translational improvements to the `septic_patients` dataset and the column `bactid` now has the new class `"bactid"`
* Small improvements to the `microorganisms` dataset (especially for *Salmonella*) and the column `bactid` now has the new class `"bactid"`
@@ -1051,7 +1194,7 @@ We've got a new website: [https://msberends.gitlab.io/AMR](https://msberends.git
* Added support for character vector in `join` functions
* Added warnings when a join results in more rows after than before the join
* Altered `%like%` to make it case insensitive
* For parameters of functions `first_isolate` and `EUCAST_rules` column names are now case-insensitive
* For arguments of functions `first_isolate` and `EUCAST_rules` column names are now case-insensitive
* Functions `as.rsi` and `as.mic` now add the package name and version as attributes
#### Other
+562 -68
View File
@@ -1,15 +1,15 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
# Diagnostics & Advice, and University Medical Center Groningen. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
# faster implementation of left_join than using merge() by poorman - we use match():
@@ -37,18 +37,18 @@ pm_left_join <- function(x, y, by = NULL, suffix = c(".x", ".y")) {
if (length(by) == 1) {
by <- rep(by, 2)
}
int_x <- colnames(x) %in% colnames(y) & colnames(x) != by[1]
int_y <- colnames(y) %in% colnames(x) & colnames(y) != by[2]
colnames(x)[int_x] <- paste0(colnames(x)[int_x], suffix[1L])
colnames(y)[int_y] <- paste0(colnames(y)[int_y], suffix[2L])
merged <- cbind(x,
y[match(x[, by[1], drop = TRUE],
y[, by[2], drop = TRUE]),
colnames(y)[!colnames(y) %in% colnames(x) & !colnames(y) == by[2]],
drop = FALSE])
rownames(merged) <- NULL
merged
}
@@ -81,40 +81,56 @@ check_dataset_integrity <- function() {
overwritten <- data_in_pkg[data_in_pkg %in% data_in_globalenv]
# exception for example_isolates
overwritten <- overwritten[overwritten != "example_isolates"]
stop_if(length(overwritten) > 0,
"the following data set is overwritten by your global environment and prevents the AMR package from working correctly:\n",
paste0("'", overwritten, "'", collapse = ", "),
".\nPlease rename your object before using this function.", call = FALSE)
if (length(overwritten) > 0) {
if (length(overwritten) > 1) {
plural <- c("s are", "", "s")
} else {
plural <- c(" is", "s", "")
}
warning_("The following data set", plural[1],
" overwritten by your global environment and prevent", plural[2],
" the AMR package from working correctly: ",
vector_and(overwritten, quotes = "'"),
".\nPlease rename your object", plural[3], ".", call = FALSE)
}
# check if other packages did not overwrite our data sets
valid_microorganisms <- TRUE
valid_antibiotics <- TRUE
tryCatch({
check_microorganisms <- all(c("mo", "fullname", "kingdom", "phylum",
"class", "order", "family", "genus",
valid_microorganisms <- all(c("mo", "fullname", "kingdom", "phylum",
"class", "order", "family", "genus",
"species", "subspecies", "rank",
"species_id", "source", "ref", "prevalence") %in% colnames(microorganisms),
na.rm = TRUE)
check_antibiotics <- all(c("ab", "atc", "cid", "name", "group",
valid_antibiotics <- all(c("ab", "atc", "cid", "name", "group",
"atc_group1", "atc_group2", "abbreviations",
"synonyms", "oral_ddd", "oral_units",
"synonyms", "oral_ddd", "oral_units",
"iv_ddd", "iv_units", "loinc") %in% colnames(antibiotics),
na.rm = TRUE)
}, error = function(e) {
# package not yet loaded
require("AMR")
})
stop_if(!valid_microorganisms | !valid_antibiotics,
"the data set `microorganisms` or `antibiotics` was overwritten in your environment because another package with the same object name(s) was loaded _after_ the AMR package, preventing the AMR package from working correctly. Please load the AMR package last.")
invisible(TRUE)
}
search_type_in_df <- function(x, type, info = TRUE) {
meet_criteria(x, allow_class = "data.frame")
meet_criteria(type, allow_class = "character", has_length = 1)
# try to find columns based on type
found <- NULL
# remove attributes from other packages
x <- as.data.frame(x, stringsAsFactors = FALSE)
colnames(x) <- trimws(colnames(x))
# -- mo
if (type == "mo") {
if (any(sapply(x, is.mo))) {
found <- sort(colnames(x)[sapply(x, is.mo)])[1]
if (any(vapply(FUN.VALUE = logical(1), x, is.mo))) {
found <- sort(colnames(x)[vapply(FUN.VALUE = logical(1), x, is.mo)])[1]
} else if ("mo" %in% colnames(x) &
suppressWarnings(
all(x$mo %in% c(NA,
@@ -128,7 +144,7 @@ search_type_in_df <- function(x, type, info = TRUE) {
} else if (any(colnames(x) %like% "species")) {
found <- sort(colnames(x)[colnames(x) %like% "species"])[1]
}
}
# -- key antibiotics
if (type == "keyantibiotics") {
@@ -142,12 +158,12 @@ search_type_in_df <- function(x, type, info = TRUE) {
# WHONET support
found <- sort(colnames(x)[colnames(x) %like% "^(specimen date|specimen_date|spec_date)"])[1]
if (!any(class(pm_pull(x, found)) %in% c("Date", "POSIXct"))) {
stop(font_red(paste0("ERROR: Found column `", font_bold(found), "` to be used as input for `col_", type,
stop(font_red(paste0("Found column '", font_bold(found), "' to be used as input for `col_", type,
"`, but this column contains no valid dates. Transform its values to valid dates first.")),
call. = FALSE)
}
} else if (any(sapply(x, function(x) inherits(x, c("Date", "POSIXct"))))) {
found <- sort(colnames(x)[sapply(x, function(x) inherits(x, c("Date", "POSIXct")))])[1]
} else if (any(vapply(FUN.VALUE = logical(1), x, function(x) inherits(x, c("Date", "POSIXct"))))) {
found <- sort(colnames(x)[vapply(FUN.VALUE = logical(1), x, function(x) inherits(x, c("Date", "POSIXct")))])[1]
}
}
# -- patient id
@@ -174,25 +190,29 @@ search_type_in_df <- function(x, type, info = TRUE) {
if (!is.null(found)) {
# this column should contain logicals
if (!is.logical(x[, found, drop = TRUE])) {
message(font_red(paste0("NOTE: Column `", font_bold(found), "` found as input for `col_", type,
"`, but this column does not contain 'logical' values (TRUE/FALSE) and was ignored.")))
message_("Column '", font_bold(found), "' found as input for `col_", type,
"`, but this column does not contain 'logical' values (TRUE/FALSE) and was ignored.",
add_fn = font_red)
found <- NULL
}
}
}
if (!is.null(found) & info == TRUE) {
msg <- paste0("NOTE: Using column `", font_bold(found), "` as input for `col_", type, "`.")
if (type %in% c("keyantibiotics", "specimen")) {
msg <- paste(msg, "Use", font_bold(paste0("col_", type), "= FALSE"), "to prevent this.")
if (message_not_thrown_before(fn = paste0("search_", type))) {
msg <- paste0("Using column '", font_bold(found), "' as input for `col_", type, "`.")
if (type %in% c("keyantibiotics", "specimen")) {
msg <- paste(msg, "Use", font_bold(paste0("col_", type), "= FALSE"), "to prevent this.")
}
message_(msg)
remember_thrown_message(fn = paste0("search_", type))
}
message(font_blue(msg))
}
found
}
is_possibly_regex <- function(x) {
tryCatch(sapply(strsplit(x, ""),
tryCatch(vapply(FUN.VALUE = character(1), strsplit(x, ""),
function(y) any(y %in% c("$", "(", ")", "*", "+", "-", ".", "?", "[", "]", "^", "{", "|", "}", "\\"), na.rm = TRUE)),
error = function(e) rep(TRUE, length(x)))
}
@@ -200,7 +220,7 @@ is_possibly_regex <- function(x) {
stop_ifnot_installed <- function(package) {
# no "utils::installed.packages()" since it requires non-staged install since R 3.6.0
# https://developer.r-project.org/Blog/public/2019/02/14/staged-install/index.html
sapply(package, function(pkg)
vapply(FUN.VALUE = character(1), package, function(pkg)
tryCatch(get(".packageName", envir = asNamespace(pkg)),
error = function(e) {
if (package == "rstudioapi") {
@@ -219,11 +239,12 @@ import_fn <- function(name, pkg, error_on_fail = TRUE) {
stop_ifnot_installed(pkg)
}
tryCatch(
get(name, envir = asNamespace(pkg)),
# don't use get() to avoid fetching non-API functions
getExportedValue(name = name, ns = asNamespace(pkg)),
error = function(e) {
if (isTRUE(error_on_fail)) {
stop_("function ", name, "() not found in package '", pkg,
"'. Please create an issue at https://github.com/msberends/AMR/issues. Many thanks!",
stop_("function ", name, "() is not an exported object from package '", pkg,
"'. Please create an issue at https://github.com/msberends/AMR/issues. Many thanks!",
call = FALSE)
} else {
return(NULL)
@@ -231,6 +252,103 @@ import_fn <- function(name, pkg, error_on_fail = TRUE) {
})
}
# this alternative wrapper to the message(), warning() and stop() functions:
# - wraps text to never break lines within words
# - ignores formatted text while wrapping
# - adds indentation dependent on the type of message (such as NOTE)
# - can add additional formatting functions like blue or bold text
word_wrap <- function(...,
add_fn = list(),
as_note = FALSE,
width = 0.95 * getOption("width"),
extra_indent = 0) {
msg <- paste0(c(...), collapse = "")
if (isTRUE(as_note)) {
msg <- paste0("NOTE: ", gsub("^note:? ?", "", msg, ignore.case = TRUE))
}
if (msg %like% "\n") {
# run word_wraps() over every line here, bind them and return again
return(paste0(vapply(FUN.VALUE = character(1),
trimws(unlist(strsplit(msg, "\n")), which = "right"),
word_wrap,
add_fn = add_fn,
as_note = FALSE,
width = width,
extra_indent = extra_indent),
collapse = "\n"))
}
# we need to correct for already applied style, that adds text like "\033[31m\"
msg_stripped <- font_stripstyle(msg)
# where are the spaces now?
msg_stripped_wrapped <- paste0(strwrap(msg_stripped,
simplify = TRUE,
width = width),
collapse = "\n")
msg_stripped_wrapped <- paste0(unlist(strsplit(msg_stripped_wrapped, "(\n|\\*\\|\\*)")),
collapse = "\n")
msg_stripped_spaces <- which(unlist(strsplit(msg_stripped, "")) == " ")
msg_stripped_wrapped_spaces <- which(unlist(strsplit(msg_stripped_wrapped, "")) != "\n")
# so these are the indices of spaces that need to be replaced
replace_spaces <- which(!msg_stripped_spaces %in% msg_stripped_wrapped_spaces)
# put it together
msg <- unlist(strsplit(msg, " "))
msg[replace_spaces] <- paste0(msg[replace_spaces], "\n")
msg <- paste0(msg, collapse = " ")
msg <- gsub("\n ", "\n", msg, fixed = TRUE)
if (msg_stripped %like% "^NOTE: ") {
indentation <- 6 + extra_indent
} else if (msg_stripped %like% "^=> ") {
indentation <- 3 + extra_indent
} else {
indentation <- 0 + extra_indent
}
msg <- gsub("\n", paste0("\n", strrep(" ", indentation)), msg, fixed = TRUE)
# remove trailing empty characters
msg <- gsub("(\n| )+$", "", msg)
if (length(add_fn) > 0) {
if (!is.list(add_fn)) {
add_fn <- list(add_fn)
}
for (i in seq_len(length(add_fn))) {
msg <- add_fn[[i]](msg)
}
}
# format backticks
msg <- gsub("(`.+?`)", font_grey_bg("\\1"), msg)
msg
}
message_ <- function(...,
appendLF = TRUE,
add_fn = list(font_blue),
as_note = TRUE) {
message(word_wrap(...,
add_fn = add_fn,
as_note = as_note),
appendLF = appendLF)
}
warning_ <- function(...,
add_fn = list(),
immediate = FALSE,
call = TRUE) {
warning(word_wrap(...,
add_fn = add_fn,
as_note = FALSE),
immediate. = immediate,
call. = call)
}
# this alternative to the stop() function:
# - adds the function name where the error was thrown
# - wraps text to never break lines within words
stop_ <- function(..., call = TRUE) {
msg <- paste0(c(...), collapse = "")
if (!isFALSE(call)) {
@@ -242,6 +360,7 @@ stop_ <- function(..., call = TRUE) {
}
msg <- paste0("in ", call, "(): ", msg)
}
msg <- word_wrap(msg, add_fn = list(), as_note = FALSE)
stop(msg, call. = FALSE)
}
@@ -286,7 +405,7 @@ stop_ifnot <- function(expr, ..., call = TRUE) {
class_integrity_check <- function(value, type, check_vector) {
if (!all(value[!is.na(value)] %in% check_vector)) {
warning(paste0("invalid ", type, ", NA generated"), call. = FALSE)
warning_(paste0("invalid ", type, ", NA generated"), call = FALSE)
value[!value %in% check_vector] <- NA
}
value
@@ -317,6 +436,7 @@ dataset_UTF8_to_ASCII <- function(df) {
df
}
# for eucast_rules() and mdro(), creates markdown output with URLs and names
create_ab_documentation <- function(ab) {
ab_names <- ab_name(ab, language = NULL, tolower = TRUE)
ab <- ab[order(ab_names)]
@@ -329,8 +449,339 @@ create_ab_documentation <- function(ab) {
out
}
vector_or <- function(v, quotes = TRUE, reverse = FALSE, sort = TRUE, last_sep = " or ") {
# makes unique and sorts, and this also removed NAs
v <- unique(v)
if (isTRUE(sort)) {
v <- sort(v)
}
if (isTRUE(reverse)) {
v <- rev(v)
}
if (isTRUE(quotes)) {
quotes <- '"'
} else if (isFALSE(quotes)) {
quotes <- ""
} else {
quotes <- quotes[1L]
}
if (length(v) == 1) {
return(paste0(quotes, v, quotes))
}
if (identical(v, c("I", "R", "S"))) {
# class <rsi> should be sorted like this
v <- c("R", "S", "I")
}
# all commas except for last item, so will become '"val1", "val2", "val3" or "val4"'
paste0(paste0(quotes, v[seq_len(length(v) - 1)], quotes, collapse = ", "),
last_sep, paste0(quotes, v[length(v)], quotes))
}
vector_and <- function(v, quotes = TRUE, reverse = FALSE, sort = TRUE) {
vector_or(v = v, quotes = quotes, reverse = reverse, sort = sort, last_sep = " and ")
}
format_class <- function(class, plural) {
class.bak <- class
class[class == "numeric"] <- "number"
class[class == "integer"] <- "whole number"
if (all(c("numeric", "integer") %in% class.bak, na.rm = TRUE)) {
class[class %in% c("number", "whole number")] <- "(whole) number"
}
class[class == "character"] <- "text string"
class[class %in% c("Date", "POSIXt")] <- "date"
class[class != class.bak] <- paste0(ifelse(plural, "", "a "),
class[class != class.bak],
ifelse(plural, "s", ""))
# exceptions
class[class == "logical"] <- ifelse(plural, "a vector of `TRUE`/`FALSE`", "`TRUE` or `FALSE`")
if ("data.frame" %in% class) {
class <- "a data set"
}
if ("list" %in% class) {
class <- "a list"
}
if ("matrix" %in% class) {
class <- "a matrix"
}
if ("isolate_identifier" %in% class) {
class <- "created with isolate_identifier()"
}
if (any(c("mo", "ab", "rsi", "disk", "mic") %in% class)) {
class <- paste0("of class <", class[1L], ">")
}
class[class == class.bak] <- paste0("of class <", class[class == class.bak], ">")
# output
vector_or(class, quotes = FALSE)
}
# a check for every single argument in all functions
meet_criteria <- function(object,
allow_class = NULL,
has_length = NULL,
looks_like = NULL,
is_in = NULL,
is_positive = NULL,
is_finite = NULL,
contains_column_class = NULL,
allow_NULL = FALSE,
allow_NA = FALSE,
ignore.case = FALSE,
.call_depth = 0) { # depth in calling
obj_name <- deparse(substitute(object))
call_depth <- -2 - abs(.call_depth)
# if object is missing, or another error:
tryCatch(invisible(object),
error = function(e) pkg_env$meet_criteria_error_txt <- e$message)
if (!is.null(pkg_env$meet_criteria_error_txt)) {
error_txt <- pkg_env$meet_criteria_error_txt
pkg_env$meet_criteria_error_txt <- NULL
stop(error_txt, call. = FALSE) # don't use stop_() here, pkg may not be loaded yet
}
pkg_env$meet_criteria_error_txt <- NULL
if (is.null(object)) {
stop_if(allow_NULL == FALSE, "argument `", obj_name, "` must not be NULL", call = call_depth)
return(invisible())
}
if (is.null(dim(object)) && length(object) == 1 && suppressWarnings(is.na(object))) { # suppressWarnings for functions
stop_if(allow_NA == FALSE, "argument `", obj_name, "` must not be NA", call = call_depth)
return(invisible())
}
if (!is.null(allow_class)) {
stop_ifnot(inherits(object, allow_class), "argument `", obj_name,
"` must be ", format_class(allow_class, plural = isTRUE(has_length > 1)),
", i.e. not be ", format_class(class(object), plural = isTRUE(has_length > 1)),
call = call_depth)
# check data.frames for data
if (inherits(object, "data.frame")) {
stop_if(any(dim(object) == 0),
"the data provided in argument `", obj_name,
"` must contain rows and columns (current dimensions: ",
paste(dim(object), collapse = "x"), ")",
call = call_depth)
}
}
if (!is.null(has_length)) {
stop_ifnot(length(object) %in% has_length, "argument `", obj_name,
"` must ", # ifelse(allow_NULL, "be NULL or must ", ""),
"be of length ", vector_or(has_length, quotes = FALSE),
", not ", length(object),
call = call_depth)
}
if (!is.null(looks_like)) {
stop_ifnot(object %like% looks_like, "argument `", obj_name,
"` must ", # ifelse(allow_NULL, "be NULL or must ", ""),
"resemble the regular expression \"", looks_like, "\"",
call = call_depth)
}
if (!is.null(is_in)) {
if (ignore.case == TRUE) {
object <- tolower(object)
is_in <- tolower(is_in)
}
stop_ifnot(all(object %in% is_in, na.rm = TRUE), "argument `", obj_name,
"` must be ",
ifelse(!is.null(has_length) && length(has_length) == 1 && has_length == 1, "either ", ""),
vector_or(is_in, quotes = !isTRUE(any(c("double", "numeric", "integer") %in% allow_class))),
ifelse(allow_NA == TRUE, ", or NA", ""),
call = call_depth)
}
if (!is.null(is_positive)) {
stop_if(is.numeric(object) && !all(object > 0, na.rm = TRUE), "argument `", obj_name,
"` must ",
ifelse(!is.null(has_length) && length(has_length) == 1 && has_length == 1,
"be a positive number",
"all be positive numbers"),
" (higher than zero)",
call = call_depth)
}
if (!is.null(is_finite)) {
stop_if(is.numeric(object) && !all(is.finite(object[!is.na(object)]), na.rm = TRUE), "argument `", obj_name,
"` must ",
ifelse(!is.null(has_length) && length(has_length) == 1 && has_length == 1,
"be a finite number",
"all be finite numbers"),
" (i.e., not be infinite)",
call = call_depth)
}
if (!is.null(contains_column_class)) {
stop_ifnot(any(vapply(FUN.VALUE = logical(1),
object,
function(col, columns_class = contains_column_class) {
inherits(col, columns_class)
}), na.rm = TRUE),
"the data provided in argument `", obj_name,
"` must contain at least one column of class <", contains_column_class, ">. ",
"See ?as.", contains_column_class, ".",
call = call_depth)
}
return(invisible())
}
get_current_data <- function(arg_name, call) {
# try dplyr::cur_data_all() first to support dplyr groups
# only useful for e.g. dplyr::filter(), dplyr::mutate() and dplyr::summarise()
# not useful (throws error) with e.g. dplyr::select() - but that will be caught later in this function
cur_data_all <- import_fn("cur_data_all", "dplyr", error_on_fail = FALSE)
if (!is.null(cur_data_all)) {
out <- tryCatch(cur_data_all(), error = function(e) NULL)
if (is.data.frame(out)) {
return(out)
}
}
if (as.double(R.Version()$major) + (as.double(R.Version()$minor) / 10) < 3.2) {
# R-3.0 and R-3.1 do not have an `x` element in the call stack, rendering this function useless
if (is.na(arg_name)) {
# like in carbapenems() etc.
warning_("this function can only be used in R >= 3.2", call = call)
return(data.frame())
} else {
stop_("argument `", arg_name, "` is missing with no default", call = call)
}
}
# try a (base R) method, by going over the complete system call stack with sys.frames()
not_set <- TRUE
frms <- lapply(sys.frames(), function(el) {
if (not_set == TRUE && ".Generic" %in% names(el)) {
if (tryCatch(".data" %in% names(el) && is.data.frame(el$`.data`), error = function(e) FALSE)) {
# dplyr? - an element `.data` will be in the system call stack
# will be used in dplyr::select() (but not in dplyr::filter(), dplyr::mutate() or dplyr::summarise())
not_set <<- FALSE
el$`.data`
} else if (tryCatch(any(c("x", "xx") %in% names(el)), error = function(e) FALSE)) {
# otherwise try base R:
# an element `x` will be in this environment for only cols, e.g. `example_isolates[, carbapenems()]`
# an element `xx` will be in this environment for rows + cols, e.g. `example_isolates[c(1:3), carbapenems()]`
if (tryCatch(is.data.frame(el$xx), error = function(e) FALSE)) {
not_set <<- FALSE
el$xx
} else if (tryCatch(is.data.frame(el$x))) {
not_set <<- FALSE
el$x
} else {
NULL
}
} else {
NULL
}
} else {
NULL
}
})
vars_df <- tryCatch(frms[[which(!vapply(FUN.VALUE = logical(1), frms, is.null))]], error = function(e) NULL)
if (is.data.frame(vars_df)) {
return(vars_df)
}
# nothing worked, so:
if (is.na(arg_name)) {
if (isTRUE(is.numeric(call))) {
fn <- as.character(sys.call(call + 1)[1])
examples <- paste0(", e.g.:\n",
" your_data %>% select(", fn, "())\n",
" your_data %>% select(column_a, column_b, ", fn, "())\n",
" your_data[, ", fn, "()]\n",
' your_data[, c("column_a", "column_b", ', fn, "())]")
} else {
examples <- ""
}
stop_("this function must be used inside valid dplyr selection verbs or inside a data.frame call",
examples,
call = call)
} else {
stop_("argument `", arg_name, "` is missing with no default", call = call)
}
}
get_current_column <- function() {
# try dplyr::cur_columns() first
cur_column <- import_fn("cur_column", "dplyr", error_on_fail = FALSE)
if (!is.null(cur_column)) {
out <- tryCatch(cur_column(), error = function(e) NULL)
if (!is.null(out)) {
return(out)
}
}
# cur_column() doesn't always work (only allowed for conditions set by dplyr), but it's probably still possible:
frms <- lapply(sys.frames(), function(el) {
if ("i" %in% names(el)) {
if ("tibble_vars" %in% names(el)) {
# for mutate_if()
el$tibble_vars[el$i]
} else {
# for mutate(across())
df <- tryCatch(get_current_data(NA, 0), error = function(e) NULL)
if (is.data.frame(df)) {
colnames(df)[el$i]
} else {
el$i
}
}
} else {
NULL
}
})
vars <- unlist(frms)
if (length(vars) > 0) {
vars[length(vars)]
} else {
# not found, so:
NULL
}
}
is_null_or_grouped_tbl <- function(x) {
# attribute "grouped_df" might change at one point, so only set in one place; here.
is.null(x) || inherits(x, "grouped_df")
}
unique_call_id <- function(entire_session = FALSE) {
if (entire_session == TRUE) {
c(envir = "session",
call = "session")
} else {
# combination of environment ID (like "0x7fed4ee8c848")
# and highest system call
c(envir = gsub("<environment: (.*)>", "\\1", utils::capture.output(sys.frames()[[1]])),
call = paste0(deparse(sys.calls()[[1]]), collapse = ""))
}
}
remember_thrown_message <- function(fn, entire_session = FALSE) {
# this is to prevent that messages/notes will be printed for every dplyr group
# e.g. this would show a msg 4 times: example_isolates %>% group_by(hospital_id) %>% filter(mo_is_gram_negative())
assign(x = paste0("thrown_msg.", fn),
value = unique_call_id(entire_session = entire_session),
envir = pkg_env)
}
message_not_thrown_before <- function(fn, entire_session = FALSE) {
is.null(pkg_env[[paste0("thrown_msg.", fn)]]) || !identical(pkg_env[[paste0("thrown_msg.", fn)]], unique_call_id(entire_session))
}
reset_all_thrown_messages <- function() {
# for unit tests, where the environment and highest system call do not change
pkg_env_contents <- ls(envir = pkg_env)
rm(list = pkg_env_contents[pkg_env_contents %like% "^thrown_msg."],
envir = pkg_env)
}
has_colour <- function() {
# this is a base R version of crayon::has_color
# this is a base R version of crayon::has_color, but disables colours on emacs
if (Sys.getenv("EMACS") != "" || Sys.getenv("INSIDE_EMACS") != "") {
# disable on emacs, which only supports 8 colours
return(FALSE)
}
enabled <- getOption("crayon.enabled")
if (!is.null(enabled)) {
return(isTRUE(enabled))
@@ -360,33 +811,19 @@ has_colour <- function() {
}
return(FALSE)
}
emacs_version <- function() {
ver <- Sys.getenv("INSIDE_EMACS")
if (ver == "") {
return(NA_integer_)
}
ver <- gsub("'", "", ver)
ver <- strsplit(ver, ",", fixed = TRUE)[[1]]
ver <- strsplit(ver, ".", fixed = TRUE)[[1]]
as.numeric(ver)
}
if ((Sys.getenv("EMACS") != "" || Sys.getenv("INSIDE_EMACS") != "") &&
!is.na(emacs_version()[1]) && emacs_version()[1] >= 23) {
return(TRUE)
}
if ("COLORTERM" %in% names(Sys.getenv())) {
return(TRUE)
}
if (Sys.getenv("TERM") == "dumb") {
return(FALSE)
}
grepl(pattern = "^screen|^xterm|^vt100|color|ansi|cygwin|linux",
grepl(pattern = "^screen|^xterm|^vt100|color|ansi|cygwin|linux",
x = Sys.getenv("TERM"),
ignore.case = TRUE,
perl = TRUE)
}
# the crayon colours
# set colours if console has_colour()
try_colour <- function(..., before, after, collapse = " ") {
txt <- paste0(unlist(list(...)), collapse = collapse)
if (isTRUE(has_colour())) {
@@ -429,9 +866,27 @@ font_subtle <- function(..., collapse = " ") {
font_grey <- function(..., collapse = " ") {
try_colour(..., before = "\033[38;5;249m", after = "\033[39m", collapse = collapse)
}
font_grey_bg <- function(..., collapse = " ") {
if (tryCatch(rstudioapi::getThemeInfo()$dark == TRUE, error = function(e) FALSE)) {
# similar to HTML #444444
try_colour(..., before = "\033[48;5;238m", after = "\033[49m", collapse = collapse)
} else {
# similar to HTML #eeeeee
try_colour(..., before = "\033[48;5;254m", after = "\033[49m", collapse = collapse)
}
}
font_green_bg <- function(..., collapse = " ") {
try_colour(..., before = "\033[42m", after = "\033[49m", collapse = collapse)
}
font_rsi_R_bg <- function(..., collapse = " ") {
try_colour(..., before = "\033[48;5;210m", after = "\033[49m", collapse = collapse)
}
font_rsi_S_bg <- function(..., collapse = " ") {
try_colour(..., before = "\033[48;5;113m", after = "\033[49m", collapse = collapse)
}
font_rsi_I_bg <- function(..., collapse = " ") {
try_colour(..., before = "\033[48;5;185m", after = "\033[49m", collapse = collapse)
}
font_red_bg <- function(..., collapse = " ") {
try_colour(..., before = "\033[41m", after = "\033[49m", collapse = collapse)
}
@@ -464,7 +919,7 @@ progress_ticker <- function(n = 1, n_min = 0, ...) {
pb$kill <- function() {
invisible()
}
structure(pb, class = "txtProgressBar")
set_clean_class(pb, new_class = "txtProgressBar")
} else if (n >= n_min) {
pb <- utils::txtProgressBar(max = n, style = 3)
pb$tick <- function() {
@@ -474,10 +929,38 @@ progress_ticker <- function(n = 1, n_min = 0, ...) {
}
}
set_clean_class <- function(x, new_class) {
# return the object with only the new class and no additional attributes where possible
if (is.null(x)) {
x <- NA_character_
}
if (is.factor(x)) {
# keep only levels and remove all other attributes
lvls <- levels(x)
attributes(x) <- NULL
levels(x) <- lvls
} else if (!is.list(x) && !is.function(x)) {
attributes(x) <- NULL
}
class(x) <- new_class
x
}
formatted_filesize <- function(...) {
size_kb <- file.size(...) / 1024
if (size_kb < 1) {
paste(round(size_kb, 1), "kB")
} else if (size_kb < 100) {
paste(round(size_kb, 0), "kB")
} else {
paste(round(size_kb / 1024, 1), "MB")
}
}
create_pillar_column <- function(x, ...) {
new_pillar_shaft_simple <- import_fn("new_pillar_shaft_simple", "pillar", error_on_fail = FALSE)
if (!is.null(new_pillar_shaft_simple)) {
new_pillar_shaft_simple(x, ...)
new_pillar_shaft_simple(x, ...)
} else {
# does not exist in package 'pillar' anymore
structure(list(x),
@@ -539,12 +1022,12 @@ round2 <- function(x, digits = 0, force_zero = TRUE) {
if (digits > 0 & force_zero == TRUE) {
values_trans <- val[val != as.integer(val) & !is.na(val)]
val[val != as.integer(val) & !is.na(val)] <- paste0(values_trans,
strrep("0",
max(0,
strrep("0",
max(0,
digits - nchar(
format(
as.double(
gsub(".*[.](.*)$",
gsub(".*[.](.*)$",
"\\1",
values_trans)),
scientific = FALSE)))))
@@ -555,7 +1038,7 @@ round2 <- function(x, digits = 0, force_zero = TRUE) {
# percentage from our other package: 'cleaner'
percentage <- function(x, digits = NULL, ...) {
# getdecimalplaces() function
getdecimalplaces <- function(x, minimum = 0, maximum = 3) {
if (maximum < minimum) {
@@ -564,20 +1047,20 @@ percentage <- function(x, digits = NULL, ...) {
if (minimum > maximum) {
minimum <- maximum
}
max_places <- max(unlist(lapply(strsplit(sub("0+$", "",
max_places <- max(unlist(lapply(strsplit(sub("0+$", "",
as.character(x * 100)), ".", fixed = TRUE),
function(y) ifelse(length(y) == 2, nchar(y[2]), 0))), na.rm = TRUE)
max(min(max_places,
maximum, na.rm = TRUE),
minimum, na.rm = TRUE)
}
# format_percentage() function
format_percentage <- function(x, digits = NULL, ...) {
if (is.null(digits)) {
digits <- getdecimalplaces(x)
}
# round right: percentage(0.4455) and format(as.percentage(0.4455), 1) should return "44.6%", not "44.5%"
x_formatted <- format(round2(as.double(x), digits = digits + 2) * 100,
scientific = FALSE,
@@ -588,7 +1071,7 @@ percentage <- function(x, digits = NULL, ...) {
x_formatted[!grepl(pattern = "^[0-9.,e-]+$", x = x)] <- NA_character_
x_formatted
}
# the actual working part
x <- as.double(x)
if (is.null(digits)) {
@@ -600,17 +1083,25 @@ percentage <- function(x, digits = NULL, ...) {
digits = digits, ...)
}
time_start_tracking <- function() {
pkg_env$time_start <- round(as.numeric(Sys.time()) * 1000)
}
time_track <- function(name = NULL) {
paste("(until now:", trimws(round(as.numeric(Sys.time()) * 1000) - pkg_env$time_start), "ms)")
}
# prevent dependency on package 'backports'
# these functions were not available in previous versions of R (last checked: R 4.0.2)
# these functions were not available in previous versions of R (last checked: R 4.0.3)
# see here for the full list: https://github.com/r-lib/backports
strrep <- function(x, times) {
x <- as.character(x)
if (length(x) == 0L)
if (length(x) == 0L)
return(x)
unlist(.mapply(function(x, times) {
if (is.na(x) || is.na(times))
if (is.na(x) || is.na(times))
return(NA_character_)
if (times <= 0L)
if (times <= 0L)
return("")
paste0(replicate(times, x), collapse = "")
}, list(x = x, times = times), MoreArgs = list()), use.names = FALSE)
@@ -618,9 +1109,9 @@ strrep <- function(x, times) {
trimws <- function(x, which = c("both", "left", "right")) {
which <- match.arg(which)
mysub <- function(re, x) sub(re, "", x, perl = TRUE)
if (which == "left")
if (which == "left")
return(mysub("^[ \t\r\n]+", x))
if (which == "right")
if (which == "right")
return(mysub("[ \t\r\n]+$", x))
mysub("[ \t\r\n]+$", mysub("^[ \t\r\n]+", x))
}
@@ -645,3 +1136,6 @@ str2lang <- function(s) {
isNamespaceLoaded <- function(pkg) {
pkg %in% loadedNamespaces()
}
lengths <- function(x, use.names = TRUE) {
vapply(x, length, FUN.VALUE = NA_integer_, USE.NAMES = use.names)
}
+26 -26
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
# ------------------------------------------------
@@ -388,29 +388,29 @@ pm_group_size <- function(x) {
pm_n_groups <- function(x) {
nrow(pm_group_data(x))
}
pm_group_split <- function(.data, ..., .keep = TRUE) {
dots_len <- ...length() > 0L
if (pm_has_groups(.data) && isTRUE(dots_len)) {
warning("... is ignored in pm_group_split(<grouped_df>), please use pm_group_by(..., .add = TRUE) %pm>% pm_group_split()")
}
if (!pm_has_groups(.data) && isTRUE(dots_len)) {
.data <- pm_group_by(.data, ...)
}
if (!pm_has_groups(.data) && isFALSE(dots_len)) {
return(list(.data))
}
pm_context$setup(.data)
on.exit(pm_context$clean(), add = TRUE)
pm_groups <- pm_get_groups(.data)
attr(pm_context$.data, "pm_groups") <- NULL
res <- pm_split_into_groups(pm_context$.data, pm_groups)
names(res) <- NULL
if (isFALSE(.keep)) {
res <- lapply(res, function(x) x[, !colnames(x) %in% pm_groups])
}
any_empty <- unlist(lapply(res, function(x) !(nrow(x) == 0L)))
res[any_empty]
}
# pm_group_split <- function(.data, ..., .keep = TRUE) {
# dots_len <- ...length() > 0L
# if (pm_has_groups(.data) && isTRUE(dots_len)) {
# warning("... is ignored in pm_group_split(<grouped_df>), please use pm_group_by(..., .add = TRUE) %pm>% pm_group_split()")
# }
# if (!pm_has_groups(.data) && isTRUE(dots_len)) {
# .data <- pm_group_by(.data, ...)
# }
# if (!pm_has_groups(.data) && isFALSE(dots_len)) {
# return(list(.data))
# }
# pm_context$setup(.data)
# on.exit(pm_context$clean(), add = TRUE)
# pm_groups <- pm_get_groups(.data)
# attr(pm_context$.data, "pm_groups") <- NULL
# res <- pm_split_into_groups(pm_context$.data, pm_groups)
# names(res) <- NULL
# if (isFALSE(.keep)) {
# res <- lapply(res, function(x) x[, !colnames(x) %in% pm_groups])
# }
# any_empty <- unlist(lapply(res, function(x) !(nrow(x) == 0L)))
# res[any_empty]
# }
pm_group_keys <- function(.data) {
pm_groups <- pm_get_groups(.data)
+55 -34
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,13 +20,13 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Transform input to an antibiotic ID
#' Transform Input to an Antibiotic ID
#'
#' Use this function to determine the antibiotic code of one or more antibiotics. The data set [antibiotics] will be searched for abbreviations, official names and synonyms (brand names).
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param x character vector to determine to antibiotic ID
#' @param flag_multiple_results logical to indicate whether a note should be printed to the console that probably more than one antibiotic code or name can be retrieved from a single input value.
#' @param info logical to indicate whether a progress bar should be printed
@@ -37,13 +37,14 @@
#'
#' All these properties will be searched for the user input. The [as.ab()] can correct for different forms of misspelling:
#'
#' * Wrong spelling of drug names (like "tobramicin" or "gentamycin"), which corrects for most audible similarities such as f/ph, x/ks, c/z/s, t/th, etc.
#' * Wrong spelling of drug names (such as "tobramicin" or "gentamycin"), which corrects for most audible similarities such as f/ph, x/ks, c/z/s, t/th, etc.
#' * Too few or too many vowels or consonants
#' * Switching two characters (like "mreopenem", often the case in clinical data, when doctors typed too fast)
#' * Switching two characters (such as "mreopenem", often the case in clinical data, when doctors typed too fast)
#' * Digitalised paper records, leaving artefacts like 0/o/O (zero and O's), B/8, n/r, etc.
#'
#' Use the [ab_property()] functions to get properties based on the returned antibiotic ID, see Examples.
#' Use the [`ab_*`][ab_property()] functions to get properties based on the returned antibiotic ID, see *Examples*.
#'
#' Note: the [as.ab()] and [`ab_*`][ab_property()] functions may use very long regular expression to match brand names of antimicrobial agents. This may fail on some systems.
#' @section Source:
#' World Health Organization (WHO) Collaborating Centre for Drug Statistics Methodology: \url{https://www.whocc.no/atc_ddd_index/}
#'
@@ -55,8 +56,8 @@
#' @seealso
#' * [antibiotics] for the [data.frame] that is being used to determine ATCs
#' * [ab_from_text()] for a function to retrieve antimicrobial drugs from clinical text (from health care records)
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @export
#' @examples
#' # these examples all return "ERY", the ID of erythromycin:
@@ -81,7 +82,18 @@
#' # they use as.ab() internally:
#' ab_name("J01FA01") # "Erythromycin"
#' ab_name("eryt") # "Erythromycin"
#'
#' if (require("dplyr")) {
#'
#' # you can quickly rename <rsi> columns using dplyr >= 1.0.0:
#' example_isolates %>%
#' rename_with(as.ab, where(is.rsi))
#'
#' }
as.ab <- function(x, flag_multiple_results = TRUE, info = TRUE, ...) {
meet_criteria(x, allow_class = c("character", "numeric", "integer", "factor"), allow_NA = TRUE)
meet_criteria(flag_multiple_results, allow_class = "logical", has_length = 1)
meet_criteria(info, allow_class = "logical", has_length = 1)
check_dataset_integrity()
@@ -91,19 +103,20 @@ as.ab <- function(x, flag_multiple_results = TRUE, info = TRUE, ...) {
initial_search <- is.null(list(...)$initial_search)
already_regex <- isTRUE(list(...)$already_regex)
fast_mode <- isTRUE(list(...)$fast_mode)
if (all(toupper(x) %in% antibiotics$ab)) {
# valid AB code, but not yet right class
return(structure(.Data = toupper(x),
class = c("ab", "character")))
return(set_clean_class(toupper(x),
new_class = c("ab", "character")))
}
x_bak <- x
x <- toupper(x)
# remove diacritics
x <- iconv(x, from = "UTF-8", to = "ASCII//TRANSLIT")
x <- gsub('"', "", x, fixed = TRUE)
x <- gsub("(specimen|specimen date|specimen_date|spec_date)", "", x, ignore.case = TRUE, perl = TRUE)
x <- gsub("(specimen|specimen date|specimen_date|spec_date|^dates?$)", "", x, ignore.case = TRUE, perl = TRUE)
x_bak_clean <- x
if (already_regex == FALSE) {
x_bak_clean <- generalise_antibiotic_name(x_bak_clean)
@@ -120,8 +133,8 @@ as.ab <- function(x, flag_multiple_results = TRUE, info = TRUE, ...) {
abnames <- abnames[!abnames == "clavulanic acid"]
}
if (length(abnames) > 1) {
message(font_blue(paste0("NOTE: more than one result was found for item ", index, ": ",
paste0(abnames, collapse = ", "))))
message_("More than one result was found for item ", index, ": ",
vector_and(abnames, quotes = FALSE))
}
}
found[1L]
@@ -133,6 +146,7 @@ as.ab <- function(x, flag_multiple_results = TRUE, info = TRUE, ...) {
}
for (i in seq_len(length(x))) {
if (initial_search == TRUE) {
progress$tick()
}
@@ -149,12 +163,19 @@ as.ab <- function(x, flag_multiple_results = TRUE, info = TRUE, ...) {
next
}
if (isTRUE(flag_multiple_results) & x[i] %like% "[ ]") {
from_text <- suppressWarnings(ab_from_text(x[i], initial_search = FALSE, translate_ab = FALSE)[[1]])
if (fast_mode == FALSE && flag_multiple_results == TRUE && x[i] %like% "[ ]") {
from_text <- tryCatch(suppressWarnings(ab_from_text(x[i], initial_search = FALSE, translate_ab = FALSE)[[1]]),
error = function(e) character(0))
} else {
from_text <- character(0)
}
# old code for phenoxymethylpenicillin (Peni V)
if (x[i] == "PNV") {
x_new[i] <- "PHN"
next
}
# exact name
found <- antibiotics[which(AB_lookup$generalised_name == x[i]), ]$ab
if (length(found) > 0) {
@@ -263,8 +284,8 @@ as.ab <- function(x, flag_multiple_results = TRUE, info = TRUE, ...) {
}
# INITIAL SEARCH - More uncertain results ----
if (initial_search == TRUE) {
if (initial_search == TRUE && fast_mode == FALSE) {
# only run on first try
# try by removing all spaces
@@ -339,10 +360,11 @@ as.ab <- function(x, flag_multiple_results = TRUE, info = TRUE, ...) {
# try from a bigger text, like from a health care record, see ?ab_from_text
# already calculated above if flag_multiple_results = TRUE
if (isTRUE(flag_multiple_results)) {
if (flag_multiple_results == TRUE) {
found <- from_text[1L]
} else {
found <- suppressWarnings(ab_from_text(x[i], initial_search = FALSE, translate_ab = FALSE)[[1]][1L])
found <- tryCatch(suppressWarnings(ab_from_text(x[i], initial_search = FALSE, translate_ab = FALSE)[[1]][1L]),
error = function(e) NA_character_)
}
if (!is.na(found)) {
x_new[i] <- note_if_more_than_one_found(found, i, from_text)
@@ -431,29 +453,28 @@ as.ab <- function(x, flag_multiple_results = TRUE, info = TRUE, ...) {
x_unknown_ATCs <- x_unknown[x_unknown %like% "[A-Z][0-9][0-9][A-Z][A-Z][0-9][0-9]"]
x_unknown <- x_unknown[!x_unknown %in% x_unknown_ATCs]
if (length(x_unknown_ATCs) > 0) {
warning("These ATC codes are not (yet) in the antibiotics data set: ",
paste('"', sort(unique(x_unknown_ATCs)), '"', sep = "", collapse = ", "),
".",
call. = FALSE)
warning_("These ATC codes are not (yet) in the antibiotics data set: ",
vector_and(x_unknown_ATCs), ".",
call = FALSE)
}
if (length(x_unknown) > 0) {
warning("These values could not be coerced to a valid antimicrobial ID: ",
paste('"', sort(unique(x_unknown)), '"', sep = "", collapse = ", "),
".",
call. = FALSE)
if (length(x_unknown) > 0 & fast_mode == FALSE) {
warning_("These values could not be coerced to a valid antimicrobial ID: ",
vector_and(x_unknown), ".",
".",
call = FALSE)
}
x_result <- data.frame(x = x_bak_clean, stringsAsFactors = FALSE) %pm>%
pm_left_join(data.frame(x = x, x_new = x_new, stringsAsFactors = FALSE), by = "x") %pm>%
pm_pull(x_new)
pm_pull(x_new)
if (length(x_result) == 0) {
x_result <- NA_character_
}
structure(.Data = x_result,
class = c("ab", "character"))
set_clean_class(x_result,
new_class = c("ab", "character"))
}
#' @rdname as.ab
+102 -54
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,23 +20,33 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Antibiotic class selectors
#' Antibiotic Class Selectors
#'
#' Use these selection helpers inside any function that allows [Tidyverse selection helpers](https://tidyselect.r-lib.org/reference/language.html), like `dplyr::select()` or `tidyr::pivot_longer()`. They help to select the columns of antibiotics that are of a specific antibiotic class, without the need to define the columns or antibiotic abbreviations.
#' These functions help to select the columns of antibiotics that are of a specific antibiotic class, without the need to define the columns or antibiotic abbreviations. \strong{\Sexpr{ifelse(as.double(R.Version()$major) + (as.double(R.Version()$minor) / 10) < 3.2, paste0("NOTE: THESE FUNCTIONS DO NOT WORK ON YOUR CURRENT R VERSION. These functions require R version 3.2 or later - you have ", R.version.string, "."), "")}}
#' @inheritSection lifecycle Stable Lifecycle
#' @param only_rsi_columns a logical to indicate whether only columns of class [`<rsi>`]([rsi]) must be selected (defaults to `FALSE`)
#' @inheritParams filter_ab_class
#' @details All columns will be searched for known antibiotic names, abbreviations, brand names and codes (ATC, EARS-Net, WHO, etc.) in the [antibiotics] data set. This means that a selector like e.g. [aminoglycosides()] will pick up column names like 'gen', 'genta', 'J01GB03', 'tobra', 'Tobracin', etc.
#' @details \strong{\Sexpr{ifelse(as.double(R.Version()$major) + (as.double(R.Version()$minor) / 10) < 3.2, paste0("NOTE: THESE FUNCTIONS DO NOT WORK ON YOUR CURRENT R VERSION. These functions require R version 3.2 or later - you have ", R.version.string, "."), "")}}
#'
#' **N.B. These functions only work if the `tidyselect` package is installed**, that comes with the `dplyr` package. An error will be thrown if the `tidyselect` package is not installed, or if the functions are used outside a function that allows Tidyverse selections like `select()` or `pivot_longer()`.
#' All columns will be searched for known antibiotic names, abbreviations, brand names and codes (ATC, EARS-Net, WHO, etc.) in the [antibiotics] data set. This means that a selector like e.g. [aminoglycosides()] will pick up column names like 'gen', 'genta', 'J01GB03', 'tobra', 'Tobracin', etc.
#' @rdname antibiotic_class_selectors
#' @seealso [filter_ab_class()] for the `filter()` equivalent.
#' @name antibiotic_class_selectors
#' @export
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # `example_isolates` is a data set available in the AMR package.
#' # See ?example_isolates.
#'
#' # this will select columns 'IPM' (imipenem) and 'MEM' (meropenem):
#' example_isolates[, carbapenems()]
#' # this will select columns 'mo', 'AMK', 'GEN', 'KAN' and 'TOB':
#' example_isolates[, c("mo", aminoglycosides())]
#'
#' if (require("dplyr")) {
#'
#' # this will select columns 'IPM' (imipenem) and 'MEM' (meropenem):
@@ -54,7 +64,7 @@
#'
#' # get bug/drug combinations for only macrolides in Gram-positives:
#' example_isolates %>%
#' filter(mo_gramstain(mo) %like% "pos") %>%
#' filter(mo_is_gram_positive()) %>%
#' select(mo, macrolides()) %>%
#' bug_drug_combinations() %>%
#' format()
@@ -63,99 +73,129 @@
#' data.frame(some_column = "some_value",
#' J01CA01 = "S") %>% # ATC code of ampicillin
#' select(penicillins()) # only the 'J01CA01' column will be selected
#'
#'
#'
#' # with dplyr 1.0.0 and higher (that adds 'across()'), this is equal:
#' # (though the row names on the first are more correct)
#' example_isolates %>% filter_carbapenems("R", "all")
#' example_isolates %>% filter(across(carbapenems(), ~. == "R"))
#' }
ab_class <- function(ab_class) {
ab_selector(ab_class, function_name = "ab_class")
ab_class <- function(ab_class,
only_rsi_columns = FALSE) {
ab_selector(ab_class, function_name = "ab_class", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
aminoglycosides <- function() {
ab_selector("aminoglycoside", function_name = "aminoglycosides")
aminoglycosides <- function(only_rsi_columns = FALSE) {
ab_selector("aminoglycoside", function_name = "aminoglycosides", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
carbapenems <- function() {
ab_selector("carbapenem", function_name = "carbapenems")
carbapenems <- function(only_rsi_columns = FALSE) {
ab_selector("carbapenem", function_name = "carbapenems", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins <- function() {
ab_selector("cephalosporin", function_name = "cephalosporins")
cephalosporins <- function(only_rsi_columns = FALSE) {
ab_selector("cephalosporin", function_name = "cephalosporins", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_1st <- function() {
ab_selector("cephalosporins.*1", function_name = "cephalosporins_1st")
cephalosporins_1st <- function(only_rsi_columns = FALSE) {
ab_selector("cephalosporins.*1", function_name = "cephalosporins_1st", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_2nd <- function() {
ab_selector("cephalosporins.*2", function_name = "cephalosporins_2nd")
cephalosporins_2nd <- function(only_rsi_columns = FALSE) {
ab_selector("cephalosporins.*2", function_name = "cephalosporins_2nd", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_3rd <- function() {
ab_selector("cephalosporins.*3", function_name = "cephalosporins_3rd")
cephalosporins_3rd <- function(only_rsi_columns = FALSE) {
ab_selector("cephalosporins.*3", function_name = "cephalosporins_3rd", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_4th <- function() {
ab_selector("cephalosporins.*4", function_name = "cephalosporins_4th")
cephalosporins_4th <- function(only_rsi_columns = FALSE) {
ab_selector("cephalosporins.*4", function_name = "cephalosporins_4th", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
cephalosporins_5th <- function() {
ab_selector("cephalosporins.*5", function_name = "cephalosporins_5th")
cephalosporins_5th <- function(only_rsi_columns = FALSE) {
ab_selector("cephalosporins.*5", function_name = "cephalosporins_5th", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
fluoroquinolones <- function() {
ab_selector("fluoroquinolone", function_name = "fluoroquinolones")
fluoroquinolones <- function(only_rsi_columns = FALSE) {
ab_selector("fluoroquinolone", function_name = "fluoroquinolones", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
glycopeptides <- function() {
ab_selector("glycopeptide", function_name = "glycopeptides")
glycopeptides <- function(only_rsi_columns = FALSE) {
ab_selector("glycopeptide", function_name = "glycopeptides", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
macrolides <- function() {
ab_selector("macrolide", function_name = "macrolides")
macrolides <- function(only_rsi_columns = FALSE) {
ab_selector("macrolide", function_name = "macrolides", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
penicillins <- function() {
ab_selector("penicillin", function_name = "penicillins")
oxazolidinones <- function(only_rsi_columns = FALSE) {
ab_selector("oxazolidinone", function_name = "oxazolidinones", only_rsi_columns = only_rsi_columns)
}
#' @rdname antibiotic_class_selectors
#' @export
tetracyclines <- function() {
ab_selector("tetracycline", function_name = "tetracyclines")
penicillins <- function(only_rsi_columns = FALSE) {
ab_selector("penicillin", function_name = "penicillins", only_rsi_columns = only_rsi_columns)
}
ab_selector <- function(ab_class, function_name) {
peek_vars_tidyselect <- import_fn("peek_vars", "tidyselect")
vars_vct <- peek_vars_tidyselect(fn = function_name)
vars_df <- data.frame(as.list(vars_vct))[0, , drop = FALSE]
colnames(vars_df) <- vars_vct
ab_in_data <- get_column_abx(vars_df, info = FALSE)
#' @rdname antibiotic_class_selectors
#' @export
tetracyclines <- function(only_rsi_columns = FALSE) {
ab_selector("tetracycline", function_name = "tetracyclines", only_rsi_columns = only_rsi_columns)
}
ab_selector <- function(ab_class,
function_name,
only_rsi_columns) {
meet_criteria(ab_class, allow_class = "character", has_length = 1, .call_depth = 1)
meet_criteria(function_name, allow_class = "character", has_length = 1, .call_depth = 1)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1, .call_depth = 1)
if (as.double(R.Version()$major) + (as.double(R.Version()$minor) / 10) < 3.2) {
warning_("antibiotic class selectors such as ", function_name,
"() require R version 3.2 or later - you have ", R.version.string,
call = FALSE)
return(NULL)
}
vars_df <- get_current_data(arg_name = NA, call = -3)
# improve speed here so it will only run once when e.g. in one select call
if (!identical(pkg_env$ab_selector, unique_call_id())) {
ab_in_data <- get_column_abx(vars_df, info = FALSE, only_rsi_columns = only_rsi_columns)
pkg_env$ab_selector <- unique_call_id()
pkg_env$ab_selector_cols <- ab_in_data
} else {
ab_in_data <- pkg_env$ab_selector_cols
}
if (length(ab_in_data) == 0) {
message(font_blue("NOTE: no antimicrobial agents found."))
message_("No antimicrobial agents found.")
return(NULL)
}
@@ -172,14 +212,22 @@ ab_selector <- function(ab_class, function_name) {
}
# get the columns with a group names in the chosen ab class
agents <- ab_in_data[names(ab_in_data) %in% ab_reference$ab]
if (length(agents) == 0) {
message(font_blue(paste0("NOTE: No antimicrobial agents of class ", ab_group,
" found", examples, ".")))
} else {
message(font_blue(paste0("Selecting ", ab_group, ": ",
paste(paste0("`", font_bold(agents, collapse = NULL),
"` (", ab_name(names(agents), tolower = TRUE, language = NULL), ")"),
collapse = ", "))))
if (message_not_thrown_before(function_name)) {
if (length(agents) == 0) {
message_("No antimicrobial agents of class ", ab_group, " found", examples, ".")
} else {
agents_formatted <- paste0("'", font_bold(agents, collapse = NULL), "'")
agents_names <- ab_name(names(agents), tolower = TRUE, language = NULL)
need_name <- tolower(gsub("[^a-zA-Z]", "", agents)) != tolower(gsub("[^a-zA-Z]", "", agents_names))
agents_formatted[need_name] <- paste0(agents_formatted[need_name],
" (", agents_names[need_name], ")")
message_("Selecting ", ab_group, ": ",
ifelse(length(agents) == 1, "column ", "columns "),
vector_and(agents_formatted, quotes = FALSE),
as_note = FALSE,
extra_indent = 6)
}
remember_thrown_message(function_name)
}
unname(agents)
}
+23 -17
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,39 +20,39 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Retrieve antimicrobial drug names and doses from clinical text
#' Retrieve Antimicrobial Drug Names and Doses from Clinical Text
#'
#' Use this function on e.g. clinical texts from health care records. It returns a [list] with all antimicrobial drugs, doses and forms of administration found in the texts.
#' @inheritSection lifecycle Maturing lifecycle
#' @inheritSection lifecycle Maturing Lifecycle
#' @param text text to analyse
#' @param type type of property to search for, either `"drug"`, `"dose"` or `"administration"`, see *Examples*
#' @param collapse character to pass on to `paste(..., collapse = ...)` to only return one character per element of `text`, see *Examples*
#' @param collapse character to pass on to `paste(, collapse = ...)` to only return one character per element of `text`, see *Examples*
#' @param translate_ab if `type = "drug"`: a column name of the [antibiotics] data set to translate the antibiotic abbreviations to, using [ab_property()]. Defaults to `FALSE`. Using `TRUE` is equal to using "name".
#' @param thorough_search logical to indicate whether the input must be extensively searched for misspelling and other faulty input values. Setting this to `TRUE` will take considerably more time than when using `FALSE`. At default, it will turn `TRUE` when all input elements contain a maximum of three words.
#' @param ... parameters passed on to [as.ab()]
#' @details This function is also internally used by [as.ab()], although it then only searches for the first drug name and will throw a note if more drug names could have been returned.
#' @param ... arguments passed on to [as.ab()]
#' @details This function is also internally used by [as.ab()], although it then only searches for the first drug name and will throw a note if more drug names could have been returned. Note: the [as.ab()] function may use very long regular expression to match brand names of antimicrobial agents. This may fail on some systems.
#'
#' ## Parameter `type`
#' ## Argument `type`
#' At default, the function will search for antimicrobial drug names. All text elements will be searched for official names, ATC codes and brand names. As it uses [as.ab()] internally, it will correct for misspelling.
#'
#' With `type = "dose"` (or similar, like "dosing", "doses"), all text elements will be searched for numeric values that are higher than 100 and do not resemble years. The output will be numeric. It supports any unit (g, mg, IE, etc.) and multiple values in one clinical text, see *Examples*.
#'
#' With `type = "administration"` (or abbreviations, like "admin", "adm"), all text elements will be searched for a form of drug administration. It supports the following forms (including common abbreviations): buccal, implant, inhalation, instillation, intravenous, nasal, oral, parenteral, rectal, sublingual, transdermal and vaginal. Abbreviations for oral (such as 'po', 'per os') will become "oral", all values for intravenous (such as 'iv', 'intraven') will become "iv". It supports multiple values in one clinical text, see *Examples*.
#'
#' ## Parameter `collapse`
#' ## Argument `collapse`
#' Without using `collapse`, this function will return a [list]. This can be convenient to use e.g. inside a `mutate()`):\cr
#' `df %>% mutate(abx = ab_from_text(clinical_text))`
#'
#' The returned AB codes can be transformed to official names, groups, etc. with all [ab_property()] functions like [ab_name()] and [ab_group()], or by using the `translate_ab` parameter.
#' The returned AB codes can be transformed to official names, groups, etc. with all [`ab_*`][ab_property()] functions such as [ab_name()] and [ab_group()], or by using the `translate_ab` argument.
#'
#' With using `collapse`, this function will return a [character]:\cr
#' `df %>% mutate(abx = ab_from_text(clinical_text, collapse = "|"))`
#' @export
#' @return A [list], or a [character] if `collapse` is not `NULL`
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # mind the bad spelling of amoxicillin in this line,
#' # straight from a true health care record:
@@ -63,7 +63,7 @@
#' ab_from_text("500 mg amoxi po and 400mg cipro iv", type = "admin")
#'
#' ab_from_text("500 mg amoxi po and 400mg cipro iv", collapse = ", ")
#'
#' \donttest{
#' # if you want to know which antibiotic groups were administered, do e.g.:
#' abx <- ab_from_text("500 mg amoxi po and 400mg cipro iv")
#' ab_group(abx[[1]])
@@ -86,18 +86,24 @@
#' collapse = "|"))
#'
#' }
#' }
ab_from_text <- function(text,
type = c("drug", "dose", "administration"),
collapse = NULL,
translate_ab = FALSE,
thorough_search = NULL,
...) {
if (missing(type)) {
type <- type[1L]
}
meet_criteria(text)
meet_criteria(type, allow_class = "character", has_length = 1)
meet_criteria(collapse, has_length = 1, allow_NULL = TRUE)
meet_criteria(translate_ab, allow_NULL = FALSE) # get_translate_ab() will be more informative about what's allowed
meet_criteria(thorough_search, allow_class = "logical", has_length = 1, allow_NULL = TRUE)
type <- tolower(trimws(type))
stop_if(length(type) != 1, "`type` must be of length 1")
text <- tolower(as.character(text))
text_split_all <- strsplit(text, "[ ;.,:\\|]")
@@ -109,7 +115,7 @@ ab_from_text <- function(text,
translate_ab <- get_translate_ab(translate_ab)
if (isTRUE(thorough_search) |
(isTRUE(is.null(thorough_search)) & max(sapply(text_split_all, length), na.rm = TRUE) <= 3)) {
(isTRUE(is.null(thorough_search)) & max(vapply(FUN.VALUE = double(1), text_split_all, length), na.rm = TRUE) <= 3)) {
text_split_all <- text_split_all[nchar(text_split_all) >= 4 & grepl("[a-z]+", text_split_all)]
result <- lapply(text_split_all, function(text_split) {
progress$tick()
@@ -197,7 +203,7 @@ ab_from_text <- function(text,
# collapse text if needed
if (!is.null(collapse)) {
result <- sapply(result, function(x) {
result <- vapply(FUN.VALUE = character(1), result, function(x) {
if (length(x) == 1 & all(is.na(x))) {
NA_character_
} else {
+43 -20
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,22 +20,22 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Get properties of an antibiotic
#' Get Properties of an Antibiotic
#'
#' Use these functions to return a specific property of an antibiotic from the [antibiotics] data set. All input values will be evaluated internally with [as.ab()].
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param x any (vector of) text that can be coerced to a valid antibiotic code with [as.ab()]
#' @param tolower logical to indicate whether the first character of every output should be transformed to a lower case character. This will lead to e.g. "polymyxin B" and not "polymyxin b".
#' @param property one of the column names of one of the [antibiotics] data set
#' @param language language of the returned text, defaults to system language (see [get_locale()]) and can also be set with `getOption("AMR_locale")`. Use `language = NULL` or `language = ""` to prevent translation.
#' @param administration way of administration, either `"oral"` or `"iv"`
#' @param units a logical to indicate whether the units instead of the DDDs itself must be returned, see Examples
#' @param units a logical to indicate whether the units instead of the DDDs itself must be returned, see *Examples*
#' @param open browse the URL using [utils::browseURL()]
#' @param ... other parameters passed on to [as.ab()]
#' @details All output will be [translate]d where possible.
#' @param ... other arguments passed on to [as.ab()]
#' @details All output [will be translated][translate] where possible.
#'
#' The function [ab_url()] will return the direct URL to the official WHO website. A warning will be returned if the required ATC code is not available.
#' @inheritSection as.ab Source
@@ -48,8 +48,8 @@
#' - A [character] in all other cases
#' @export
#' @seealso [antibiotics]
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # all properties:
#' ab_name("AMX") # "Amoxicillin"
@@ -89,6 +89,10 @@
#' ab_atc("cephthriaxone")
#' ab_atc("seephthriaaksone")
ab_name <- function(x, language = get_locale(), tolower = FALSE, ...) {
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(tolower, allow_class = "logical", has_length = 1)
x <- translate_AMR(ab_validate(x = x, property = "name", ...), language = language)
if (tolower == TRUE) {
# use perl to only transform the first character
@@ -102,18 +106,21 @@ ab_name <- function(x, language = get_locale(), tolower = FALSE, ...) {
#' @aliases ATC
#' @export
ab_atc <- function(x, ...) {
meet_criteria(x, allow_NA = TRUE)
ab_validate(x = x, property = "atc", ...)
}
#' @rdname ab_property
#' @export
ab_cid <- function(x, ...) {
meet_criteria(x, allow_NA = TRUE)
ab_validate(x = x, property = "cid", ...)
}
#' @rdname ab_property
#' @export
ab_synonyms <- function(x, ...) {
meet_criteria(x, allow_NA = TRUE)
syns <- ab_validate(x = x, property = "synonyms", ...)
names(syns) <- x
if (length(syns) == 1) {
@@ -126,30 +133,38 @@ ab_synonyms <- function(x, ...) {
#' @rdname ab_property
#' @export
ab_tradenames <- function(x, ...) {
meet_criteria(x, allow_NA = TRUE)
ab_synonyms(x, ...)
}
#' @rdname ab_property
#' @export
ab_group <- function(x, language = get_locale(), ...) {
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(ab_validate(x = x, property = "group", ...), language = language)
}
#' @rdname ab_property
#' @export
ab_atc_group1 <- function(x, language = get_locale(), ...) {
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(ab_validate(x = x, property = "atc_group1", ...), language = language)
}
#' @rdname ab_property
#' @export
ab_atc_group2 <- function(x, language = get_locale(), ...) {
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(ab_validate(x = x, property = "atc_group2", ...), language = language)
}
#' @rdname ab_property
#' @export
ab_loinc <- function(x, ...) {
meet_criteria(x, allow_NA = TRUE)
loincs <- ab_validate(x = x, property = "loinc", ...)
names(loincs) <- x
if (length(loincs) == 1) {
@@ -162,7 +177,10 @@ ab_loinc <- function(x, ...) {
#' @rdname ab_property
#' @export
ab_ddd <- function(x, administration = "oral", units = FALSE, ...) {
stop_ifnot(administration %in% c("oral", "iv"), "`administration` must be 'oral' or 'iv'")
meet_criteria(x, allow_NA = TRUE)
meet_criteria(administration, is_in = c("oral", "iv"), has_length = 1)
meet_criteria(units, allow_class = "logical", has_length = 1)
ddd_prop <- administration
if (units == TRUE) {
ddd_prop <- paste0(ddd_prop, "_units")
@@ -175,6 +193,9 @@ ab_ddd <- function(x, administration = "oral", units = FALSE, ...) {
#' @rdname ab_property
#' @export
ab_info <- function(x, language = get_locale(), ...) {
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x <- as.ab(x, ...)
list(ab = as.character(x),
atc = ab_atc(x),
@@ -194,6 +215,9 @@ ab_info <- function(x, language = get_locale(), ...) {
#' @rdname ab_property
#' @export
ab_url <- function(x, open = FALSE, ...) {
meet_criteria(x, allow_NA = TRUE)
meet_criteria(open, allow_class = "logical", has_length = 1)
ab <- as.ab(x = x, ... = ...)
u <- paste0("https://www.whocc.no/atc_ddd_index/?code=", ab_atc(ab), "&showdescription=no")
u[is.na(ab_atc(ab))] <- NA_character_
@@ -201,12 +225,12 @@ ab_url <- function(x, open = FALSE, ...) {
NAs <- ab_name(ab, tolower = TRUE, language = NULL)[!is.na(ab) & is.na(ab_atc(ab))]
if (length(NAs) > 0) {
warning("No ATC code available for ", paste0(NAs, collapse = ", "), ".")
warning_("No ATC code available for ", vector_and(NAs, quotes = FALSE), ".")
}
if (open == TRUE) {
if (length(u) > 1 & !is.na(u[1L])) {
warning("only the first URL will be opened, as `browseURL()` only suports one string.")
warning_("Only the first URL will be opened, as `browseURL()` only suports one string.")
}
if (!is.na(u[1L])) {
utils::browseURL(u[1L])
@@ -218,10 +242,9 @@ ab_url <- function(x, open = FALSE, ...) {
#' @rdname ab_property
#' @export
ab_property <- function(x, property = "name", language = get_locale(), ...) {
stop_if(length(property) != 1L, "'property' must be of length 1.")
stop_ifnot(property %in% colnames(antibiotics),
"invalid property: '", property, "' - use a column name of the `antibiotics` data set")
meet_criteria(x, allow_NA = TRUE)
meet_criteria(property, is_in = colnames(antibiotics), has_length = 1)
meet_criteria(language, is_in = c(LANGUAGES_SUPPORTED, ""), has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(ab_validate(x = x, property = property, ...), language = language)
}
@@ -229,7 +252,7 @@ ab_validate <- function(x, property, ...) {
check_dataset_integrity()
# try to catch an error when inputting an invalid parameter
# try to catch an error when inputting an invalid argument
# so the 'call.' can be set to FALSE
tryCatch(x[1L] %in% antibiotics[1, property],
error = function(e) stop(e$message, call. = FALSE))
@@ -237,10 +260,10 @@ ab_validate <- function(x, property, ...) {
if (!all(x %in% antibiotics[, property])) {
x <- data.frame(ab = as.ab(x, ...), stringsAsFactors = FALSE) %pm>%
pm_left_join(antibiotics, by = "ab") %pm>%
pm_pull(property)
pm_pull(property)
}
if (property == "ab") {
return(structure(x, class = property))
return(set_clean_class(x, new_class = c("ab", "character")))
} else if (property == "cid") {
return(as.integer(x))
} else if (property %like% "ddd") {
+47 -37
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,20 +20,22 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Age in years of individuals
#' Age in Years of Individuals
#'
#' Calculates age in years based on a reference date, which is the sytem date at default.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param x date(s), will be coerced with [as.POSIXlt()]
#' @param reference reference date(s) (defaults to today), will be coerced with [as.POSIXlt()] and cannot be lower than `x`
#' @param reference reference date(s) (defaults to today), will be coerced with [as.POSIXlt()]
#' @param exact a logical to indicate whether age calculation should be exact, i.e. with decimals. It divides the number of days of [year-to-date](https://en.wikipedia.org/wiki/Year-to-date) (YTD) of `x` by the number of days in the year of `reference` (either 365 or 366).
#' @param na.rm a logical to indicate whether missing values should be removed
#' @param ... arguments passed on to [as.POSIXlt()], such as `origin`
#' @details Ages below 0 will be returned as `NA` with a warning. Ages above 120 will only give a warning.
#' @return An [integer] (no decimals) if `exact = FALSE`, a [double] (with decimals) otherwise
#' @seealso To split ages into groups, use the [age_groups()] function.
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @export
#' @examples
#' # 10 random birth dates
@@ -44,13 +46,18 @@
#' df$age_exact <- age(df$birth_date, exact = TRUE)
#'
#' df
age <- function(x, reference = Sys.Date(), exact = FALSE, na.rm = FALSE) {
age <- function(x, reference = Sys.Date(), exact = FALSE, na.rm = FALSE, ...) {
meet_criteria(x, allow_class = c("character", "Date", "POSIXt"))
meet_criteria(reference, allow_class = c("character", "Date", "POSIXt"))
meet_criteria(exact, allow_class = "logical", has_length = 1)
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
if (length(x) != length(reference)) {
stop_if(length(reference) != 1, "`x` and `reference` must be of same length, or `reference` must be of length 1.")
reference <- rep(reference, length(x))
}
x <- as.POSIXlt(x)
reference <- as.POSIXlt(reference)
x <- as.POSIXlt(x, ...)
reference <- as.POSIXlt(reference, ...)
# from https://stackoverflow.com/a/25450756/4575331
years_gap <- reference$year - x$year
@@ -76,10 +83,10 @@ age <- function(x, reference = Sys.Date(), exact = FALSE, na.rm = FALSE) {
if (any(ages < 0, na.rm = TRUE)) {
ages[ages < 0] <- NA
warning("NAs introduced for ages below 0.")
warning_("NAs introduced for ages below 0.", call = TRUE)
}
if (any(ages > 120, na.rm = TRUE)) {
warning("Some ages are above 120.")
warning_("Some ages are above 120.", call = TRUE)
}
if (isTRUE(na.rm)) {
@@ -89,26 +96,26 @@ age <- function(x, reference = Sys.Date(), exact = FALSE, na.rm = FALSE) {
ages
}
#' Split ages into age groups
#' Split Ages into Age Groups
#'
#' Split ages into age groups defined by the `split` parameter. This allows for easier demographic (antimicrobial resistance) analysis.
#' @inheritSection lifecycle Stable lifecycle
#' Split ages into age groups defined by the `split` argument. This allows for easier demographic (antimicrobial resistance) analysis.
#' @inheritSection lifecycle Stable Lifecycle
#' @param x age, e.g. calculated with [age()]
#' @param split_at values to split `x` at, defaults to age groups 0-11, 12-24, 25-54, 55-74 and 75+. See Details.
#' @param split_at values to split `x` at, defaults to age groups 0-11, 12-24, 25-54, 55-74 and 75+. See *Details*.
#' @param na.rm a [logical] to indicate whether missing values should be removed
#' @details To split ages, the input for the `split_at` parameter can be:
#' @details To split ages, the input for the `split_at` argument can be:
#'
#' * A numeric vector. A vector of e.g. `c(10, 20)` will split on 0-9, 10-19 and 20+. A value of only `50` will split on 0-49 and 50+.
#' * A numeric vector. A value of e.g. `c(10, 20)` will split `x` on 0-9, 10-19 and 20+. A value of only `50` will split `x` on 0-49 and 50+.
#' The default is to split on young children (0-11), youth (12-24), young adults (25-54), middle-aged adults (55-74) and elderly (75+).
#' * A character:
#' - `"children"` or `"kids"`, equivalent of: `c(0, 1, 2, 4, 6, 13, 18)`. This will split on 0, 1, 2-3, 4-5, 6-12, 13-17 and 18+.
#' - `"elderly"` or `"seniors"`, equivalent of: `c(65, 75, 85)`. This will split on 0-64, 65-74, 75-84, 85+.
#' - `"fives"`, equivalent of: `1:20 * 5`. This will split on 0-4, 5-9, 10-14, ..., 90-94, 95-99, 100+.
#' - `"tens"`, equivalent of: `1:10 * 10`. This will split on 0-9, 10-19, 20-29, ..., 80-89, 90-99, 100+.
#' - `"fives"`, equivalent of: `1:20 * 5`. This will split on 0-4, 5-9, ..., 95-99, 100+.
#' - `"tens"`, equivalent of: `1:10 * 10`. This will split on 0-9, 10-19, ..., 90-99, 100+.
#' @return Ordered [factor]
#' @seealso To determine ages, based on one or more reference dates, use the [age()] function.
#' @export
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' ages <- c(3, 8, 16, 54, 31, 76, 101, 43, 21)
#'
@@ -127,25 +134,28 @@ age <- function(x, reference = Sys.Date(), exact = FALSE, na.rm = FALSE) {
#' age_groups(ages, split_at = "fives")
#'
#' # split specifically for children
#' age_groups(ages, "children")
#' # same:
#' age_groups(ages, c(1, 2, 4, 6, 13, 17))
#' age_groups(ages, "children")
#'
#' \donttest{
#' # resistance of ciprofloxacine per age group
#' library(dplyr)
#' example_isolates %>%
#' filter_first_isolate() %>%
#' filter(mo == as.mo("E. coli")) %>%
#' group_by(age_group = age_groups(age)) %>%
#' select(age_group, CIP) %>%
#' ggplot_rsi(x = "age_group", minimum = 0)
#' # resistance of ciprofloxacin per age group
#' if (require("dplyr")) {
#' example_isolates %>%
#' filter_first_isolate() %>%
#' filter(mo == as.mo("E. coli")) %>%
#' group_by(age_group = age_groups(age)) %>%
#' select(age_group, CIP) %>%
#' ggplot_rsi(x = "age_group", minimum = 0)
#' }
#' }
age_groups <- function(x, split_at = c(12, 25, 55, 75), na.rm = FALSE) {
stop_ifnot(is.numeric(x), "`x` must be numeric, not ", paste0(class(x), collapse = "/"))
meet_criteria(x, allow_class = c("numeric", "integer"), is_positive = TRUE, is_finite = TRUE)
meet_criteria(split_at, allow_class = c("numeric", "integer", "character"), is_positive = TRUE, is_finite = TRUE)
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
if (any(x < 0, na.rm = TRUE)) {
x[x < 0] <- NA
warning("NAs introduced for ages below 0.")
warning_("NAs introduced for ages below 0.", call = TRUE)
}
if (is.character(split_at)) {
split_at <- split_at[1L]
@@ -169,17 +179,17 @@ age_groups <- function(x, split_at = c(12, 25, 55, 75), na.rm = FALSE) {
# turn input values to 'split_at' indices
y <- x
labs <- split_at
lbls <- split_at
for (i in seq_len(length(split_at))) {
y[x >= split_at[i]] <- i
# create labels
labs[i - 1] <- paste0(unique(c(split_at[i - 1], split_at[i] - 1)), collapse = "-")
lbls[i - 1] <- paste0(unique(c(split_at[i - 1], split_at[i] - 1)), collapse = "-")
}
# last category
labs[length(labs)] <- paste0(split_at[length(split_at)], "+")
lbls[length(lbls)] <- paste0(split_at[length(split_at)], "+")
agegroups <- factor(labs[y], levels = labs, ordered = TRUE)
agegroups <- factor(lbls[y], levels = lbls, ordered = TRUE)
if (isTRUE(na.rm)) {
agegroups <- agegroups[!is.na(agegroups)]
+17 -16
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,30 +20,30 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' The `AMR` Package
#'
#' Welcome to the `AMR` package.
#' @details
#' `AMR` is a free, open-source and independent R package to simplify the analysis and prediction of Antimicrobial Resistance (AMR) and to work with microbial and antimicrobial data and properties, by using evidence-based methods. Our aim is to provide a standard for clean and reproducible antimicrobial resistance data analysis, that can therefore empower epidemiological analyses to continuously enable surveillance and treatment evaluation in any setting.
#' `AMR` is a free, open-source and independent \R package to simplify the analysis and prediction of Antimicrobial Resistance (AMR) and to work with microbial and antimicrobial data and properties, by using evidence-based methods. Our aim is to provide a standard for clean and reproducible antimicrobial resistance data analysis, that can therefore empower epidemiological analyses to continuously enable surveillance and treatment evaluation in any setting.
#'
#' After installing this package, R knows ~70,000 distinct microbial species and all ~550 antibiotic, antimycotic and antiviral drugs by name and code (including ATC, EARS-NET, LOINC and SNOMED CT), and knows all about valid R/SI and MIC values. It supports any data format, including WHONET/EARS-Net data.
#' After installing this package, \R knows ~70,000 distinct microbial species and all ~550 antibiotic, antimycotic and antiviral drugs by name and code (including ATC, EARS-NET, LOINC and SNOMED CT), and knows all about valid R/SI and MIC values. It supports any data format, including WHONET/EARS-Net data.
#'
#' This package is fully independent of any other R package and works on Windows, macOS and Linux with all versions of R since R-3.0.0 (April 2013). It was designed to work in any setting, including those with very limited resources. It was created for both routine data analysis and academic research at the Faculty of Medical Sciences of the University of Groningen, in collaboration with non-profit organisations Certe Medical Diagnostics and Advice and University Medical Center Groningen. This R package is actively maintained and free software; you can freely use and distribute it for both personal and commercial (but not patent) purposes under the terms of the GNU General Public License version 2.0 (GPL-2), as published by the Free Software Foundation.
#' This package is fully independent of any other \R package and works on Windows, macOS and Linux with all versions of \R since R-3.0.0 (April 2013). It was designed to work in any setting, including those with very limited resources. It was created for both routine data analysis and academic research at the Faculty of Medical Sciences of the University of Groningen, in collaboration with non-profit organisations Certe Medical Diagnostics and Advice and University Medical Center Groningen. This \R package is actively maintained and free software; you can freely use and distribute it for both personal and commercial (but not patent) purposes under the terms of the GNU General Public License version 2.0 (GPL-2), as published by the Free Software Foundation.
#'
#' This package can be used for:
#' - Reference for the taxonomy of microorganisms, since the package contains all microbial (sub)species from the Catalogue of Life and List of Prokaryotic names with Standing in Nomenclature
#' - Interpreting raw MIC and disk diffusion values, based on the latest CLSI or EUCAST guidelines
#' - Retrieving antimicrobial drug names, doses and forms of administration from clinical health care records
#' - Determining first isolates to be used for AMR analysis
#' - Determining first isolates to be used for AMR data analysis
#' - Calculating antimicrobial resistance
#' - Determining multi-drug resistance (MDR) / multi-drug resistant organisms (MDRO)
#' - Calculating (empirical) susceptibility of both mono therapy and combination therapies
#' - Predicting future antimicrobial resistance using regression models
#' - Getting properties for any microorganism (like Gram stain, species, genus or family)
#' - Getting properties for any antibiotic (like name, code of EARS-Net/ATC/LOINC/PubChem, defined daily dose or trade name)
#' - Getting properties for any microorganism (such as Gram stain, species, genus or family)
#' - Getting properties for any antibiotic (such as name, code of EARS-Net/ATC/LOINC/PubChem, defined daily dose or trade name)
#' - Plotting antimicrobial resistance
#' - Applying EUCAST expert rules
#' - Getting SNOMED codes of a microorganism, or getting properties of a microorganism based on a SNOMED code
@@ -51,10 +51,10 @@
#' - Machine reading the EUCAST and CLSI guidelines from 2011-2020 to translate MIC values and disk diffusion diameters to R/SI
#' - Principal component analysis for AMR
#'
#' @section Reference data publicly available:
#' @section Reference Data Publicly Available:
#' All reference data sets (about microorganisms, antibiotics, R/SI interpretation, EUCAST rules, etc.) in this `AMR` package are publicly and freely available. We continually export our data sets to formats for use in R, SPSS, SAS, Stata and Excel. We also supply flat files that are machine-readable and suitable for input in any software program, such as laboratory information systems. Please find [all download links on our website](https://msberends.github.io/AMR/articles/datasets.html), which is automatically updated with every code change.
#' @section Read more on our website!:
#' On our website <https://msberends.github.io/AMR/> you can find [a comprehensive tutorial](https://msberends.github.io/AMR/articles/AMR.html) about how to conduct AMR analysis, the [complete documentation of all functions](https://msberends.github.io/AMR/reference/) and [an example analysis using WHONET data](https://msberends.github.io/AMR/articles/WHONET.html). As we would like to better understand the backgrounds and needs of our users, please [participate in our survey](https://msberends.github.io/AMR/survey.html)!
#' @section Read more on Our Website!:
#' On our website <https://msberends.github.io/AMR/> you can find [a comprehensive tutorial](https://msberends.github.io/AMR/articles/AMR.html) about how to conduct AMR data analysis, the [complete documentation of all functions](https://msberends.github.io/AMR/reference/) and [an example analysis using WHONET data](https://msberends.github.io/AMR/articles/WHONET.html). As we would like to better understand the backgrounds and needs of our users, please [participate in our survey](https://msberends.github.io/AMR/survey.html)!
#' @section Contact Us:
#' For suggestions, comments or questions, please contact us at:
#'
@@ -66,6 +66,7 @@
#' Post Office Box 30001 \cr
#' 9700 RB Groningen \cr
#' The Netherlands
#' <https://msberends.github.io/AMR/>
#'
#' If you have found a bug, please file a new issue at: \cr
#' <https://github.com/msberends/AMR/issues>
@@ -73,12 +74,12 @@
#' @rdname AMR
NULL
#' Plotting for classes `rsi` and `disk`
#' Plotting for Classes `rsi`, `mic` and `disk`
#'
#' Functions to print classes of the `AMR` package.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection AMR Read more on our website!
#' @param ... Parameters passed on to functions
#' @inheritSection lifecycle Stable Lifecycle
#' @inheritSection AMR Read more on Our Website!
#' @param ... Arguments passed on to functions
#' @inheritParams base::plot
#' @inheritParams graphics::barplot
#' @name plot
+21 -24
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,21 +20,21 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Get ATC properties from WHOCC website
#' Get ATC Properties from WHOCC Website
#'
#' Gets data from the WHO to determine properties of an ATC (e.g. an antibiotic), such as the name, defined daily dose (DDD) or standard unit.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param atc_code a character or character vector with ATC code(s) of antibiotic(s)
#' @param property property of an ATC code. Valid values are `"ATC"`, `"Name"`, `"DDD"`, `"U"` (`"unit"`), `"Adm.R"`, `"Note"` and `groups`. For this last option, all hierarchical groups of an ATC code will be returned, see Examples.
#' @param administration type of administration when using `property = "Adm.R"`, see Details
#' @param property property of an ATC code. Valid values are `"ATC"`, `"Name"`, `"DDD"`, `"U"` (`"unit"`), `"Adm.R"`, `"Note"` and `groups`. For this last option, all hierarchical groups of an ATC code will be returned, see *Examples*.
#' @param administration type of administration when using `property = "Adm.R"`, see *Details*
#' @param url url of website of the WHOCC. The sign `%s` can be used as a placeholder for ATC codes.
#' @param url_vet url of website of the WHOCC for veterinary medicine. The sign `%s` can be used as a placeholder for ATC_vet codes (that all start with "Q").
#' @param ... parameters to pass on to `atc_property`
#' @param ... arguments to pass on to `atc_property`
#' @details
#' Options for parameter `administration`:
#' Options for argument `administration`:
#'
#' - `"Implant"` = Implant
#' - `"Inhal"` = Inhalation
@@ -61,7 +61,7 @@
#' **N.B. This function requires an internet connection and only works if the following packages are installed: `curl`, `rvest`, `xml2`.**
#' @export
#' @rdname atc_online
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @source <https://www.whocc.no/atc_ddd_alterations__cumulative/ddd_alterations/abbrevations/>
#' @examples
#' \donttest{
@@ -78,6 +78,11 @@ atc_online_property <- function(atc_code,
administration = "O",
url = "https://www.whocc.no/atc_ddd_index/?code=%s&showdescription=no",
url_vet = "https://www.whocc.no/atcvet/atcvet_index/?code=%s&showdescription=no") {
meet_criteria(atc_code, allow_class = "character")
meet_criteria(property, allow_class = "character", has_length = 1, is_in = c("ATC", "Name", "DDD", "U", "Adm.R", "Note", "groups"), ignore.case = TRUE)
meet_criteria(administration, allow_class = "character", has_length = 1)
meet_criteria(url, allow_class = "character", has_length = 1, looks_like = "https?://")
meet_criteria(url_vet, allow_class = "character", has_length = 1, looks_like = "https?://")
has_internet <- import_fn("has_internet", "curl")
html_attr <- import_fn("html_attr", "rvest")
@@ -95,28 +100,18 @@ atc_online_property <- function(atc_code,
}
if (!has_internet()) {
message("There appears to be no internet connection, returning NA.")
message_("There appears to be no internet connection, returning NA.",
add_fn = font_red,
as_note = FALSE)
return(rep(NA, length(atc_code)))
}
stop_if(length(property) != 1L, "`property` must be of length 1")
stop_if(length(administration) != 1L, "`administration` must be of length 1")
# also allow unit as property
if (property %like% "unit") {
property <- "U"
}
# validation of properties
valid_properties <- c("ATC", "Name", "DDD", "U", "Adm.R", "Note", "groups")
valid_properties.bak <- valid_properties
property <- tolower(property)
valid_properties <- tolower(valid_properties)
stop_ifnot(property %in% valid_properties,
"Invalid `property`, use one of ", paste(valid_properties.bak, collapse = ", "))
if (property == "ddd") {
returnvalue <- rep(NA_real_, length(atc_code))
} else if (property == "groups") {
@@ -166,7 +161,7 @@ atc_online_property <- function(atc_code,
colnames(tbl) <- gsub("^atc.*", "atc", tolower(colnames(tbl)))
if (length(tbl) == 0) {
warning("ATC not found: ", atc_code[i], ". Please check ", atc_url, ".", call. = FALSE)
warning_("ATC not found: ", atc_code[i], ". Please check ", atc_url, ".", call = FALSE)
returnvalue[i] <- NA
next
}
@@ -199,11 +194,13 @@ atc_online_property <- function(atc_code,
#' @rdname atc_online
#' @export
atc_online_groups <- function(atc_code, ...) {
meet_criteria(atc_code, allow_class = "character")
atc_online_property(atc_code = atc_code, property = "groups", ...)
}
#' @rdname atc_online
#' @export
atc_online_ddd <- function(atc_code, ...) {
meet_criteria(atc_code, allow_class = "character")
atc_online_property(atc_code = atc_code, property = "ddd", ...)
}
+14 -11
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,18 +20,18 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Check availability of columns
#' Check Availability of Columns
#'
#' Easy check for data availability of all columns in a data set. This makes it easy to get an idea of which antimicrobial combinations can be used for calculation with e.g. [susceptibility()] and [resistance()].
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param tbl a [data.frame] or [list]
#' @param width number of characters to present the visual availability, defaults to filling the width of the console
#' @details The function returns a [data.frame] with columns `"resistant"` and `"visual_resistance"`. The values in that columns are calculated with [resistance()].
#' @return [data.frame] with column names of `tbl` as row names
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @export
#' @examples
#' availability(example_isolates)
@@ -43,12 +43,14 @@
#' availability()
#' }
availability <- function(tbl, width = NULL) {
stop_ifnot(is.data.frame(tbl), "`tbl` must be a data.frame")
x <- sapply(tbl, function(x) {
meet_criteria(tbl, allow_class = "data.frame")
meet_criteria(width, allow_class = c("numeric", "integer"), has_length = 1, allow_NULL = TRUE, is_positive = TRUE, is_finite = TRUE)
x <- vapply(FUN.VALUE = double(1), tbl, function(x) {
1 - sum(is.na(x)) / length(x)
})
n <- sapply(tbl, function(x) length(x[!is.na(x)]))
R <- sapply(tbl, function(x) ifelse(is.rsi(x), resistance(x, minimum = 0), NA))
n <- vapply(FUN.VALUE = double(1), tbl, function(x) length(x[!is.na(x)]))
R <- vapply(FUN.VALUE = double(1), tbl, function(x) ifelse(is.rsi(x), resistance(x, minimum = 0), NA_real_))
R_print <- character(length(R))
R_print[!is.na(R)] <- percentage(R[!is.na(R)])
R_print[is.na(R)] <- ""
@@ -83,7 +85,8 @@ availability <- function(tbl, width = NULL) {
available = percentage(x),
visual_availabilty = paste0("|", x_chars, x_chars_empty, "|"),
resistant = R_print,
visual_resistance = vis_resistance)
visual_resistance = vis_resistance,
stringsAsFactors = FALSE)
if (length(R[is.na(R)]) == ncol(tbl)) {
df[, 1:3]
} else {
+47 -29
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,19 +20,19 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Determine bug-drug combinations
#' Determine Bug-Drug Combinations
#'
#' Determine antimicrobial resistance (AMR) of all bug-drug combinations in your data set where at least 30 (default) isolates are available per species. Use [format()] on the result to prettify it to a publicable/printable format, see Examples.
#' @inheritSection lifecycle Stable lifecycle
#' Determine antimicrobial resistance (AMR) of all bug-drug combinations in your data set where at least 30 (default) isolates are available per species. Use [format()] on the result to prettify it to a publicable/printable format, see *Examples*.
#' @inheritSection lifecycle Stable Lifecycle
#' @inheritParams eucast_rules
#' @param combine_IR logical to indicate whether values R and I should be summed
#' @param add_ab_group logical to indicate where the group of the antimicrobials must be included as a first column
#' @param remove_intrinsic_resistant logical to indicate that rows and columns with 100% resistance for all tested antimicrobials must be removed from the table
#' @param FUN the function to call on the `mo` column to transform the microorganism IDs, defaults to [mo_shortname()]
#' @param translate_ab a character of length 1 containing column names of the [antibiotics] data set
#' @param FUN function to call on the `mo` column to transform the microorganism IDs, defaults to [mo_shortname()]
#' @param translate_ab character of length 1 containing column names of the [antibiotics] data set
#' @param ... arguments passed on to `FUN`
#' @inheritParams rsi_df
#' @inheritParams base::formatC
@@ -41,7 +41,7 @@
#' @rdname bug_drug_combinations
#' @return The function [bug_drug_combinations()] returns a [data.frame] with columns "mo", "ab", "S", "I", "R" and "total".
#' @source \strong{M39 Analysis and Presentation of Cumulative Antimicrobial Susceptibility Test Data, 4th Edition}, 2014, *Clinical and Laboratory Standards Institute (CLSI)*. <https://clsi.org/standards/products/microbiology/documents/m39/>.
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' \donttest{
#' x <- bug_drug_combinations(example_isolates)
@@ -61,34 +61,37 @@ bug_drug_combinations <- function(x,
col_mo = NULL,
FUN = mo_shortname,
...) {
stop_ifnot(is.data.frame(x), "`x` must be a data frame")
stop_ifnot(any(sapply(x, is.rsi), na.rm = TRUE), "No columns with class <rsi> found. See ?as.rsi.")
meet_criteria(x, allow_class = "data.frame", contains_column_class = "rsi")
meet_criteria(col_mo, allow_class = "character", is_in = colnames(x), has_length = 1, allow_NULL = TRUE)
meet_criteria(FUN, allow_class = "function", has_length = 1)
# try to find columns based on type
# -- mo
if (is.null(col_mo)) {
col_mo <- search_type_in_df(x = x, type = "mo")
stop_if(is.null(col_mo), "`col_mo` must be set")
} else {
stop_ifnot(col_mo %in% colnames(x), "column '", col_mo, "' (`col_mo`) not found")
}
stop_if(is.null(col_mo), "`col_mo` must be set")
x_class <- class(x)
x <- as.data.frame(x, stringsAsFactors = FALSE)
x[, col_mo] <- FUN(x[, col_mo, drop = TRUE], ...)
x <- x[, c(col_mo, names(which(sapply(x, is.rsi)))), drop = FALSE]
x <- x[, c(col_mo, names(which(vapply(FUN.VALUE = logical(1), x, is.rsi)))), drop = FALSE]
unique_mo <- sort(unique(x[, col_mo, drop = TRUE]))
out <- data.frame(
mo = character(0),
ab = character(0),
S = integer(0),
I = integer(0),
R = integer(0),
total = integer(0))
out <- data.frame(mo = character(0),
ab = character(0),
S = integer(0),
I = integer(0),
R = integer(0),
total = integer(0),
stringsAsFactors = FALSE)
for (i in seq_len(length(unique_mo))) {
# filter on MO group and only select R/SI columns
x_mo_filter <- x[which(x[, col_mo, drop = TRUE] == unique_mo[i]), names(which(sapply(x, is.rsi))), drop = FALSE]
x_mo_filter <- x[which(x[, col_mo, drop = TRUE] == unique_mo[i]), names(which(vapply(FUN.VALUE = logical(1), x, is.rsi))), drop = FALSE]
# turn and merge everything
pivot <- lapply(x_mo_filter, function(x) {
m <- as.matrix(table(x))
@@ -100,11 +103,13 @@ bug_drug_combinations <- function(x,
S = merged$S,
I = merged$I,
R = merged$R,
total = merged$S + merged$I + merged$R)
out <- rbind(out, out_group)
total = merged$S + merged$I + merged$R,
stringsAsFactors = FALSE)
out <- rbind(out, out_group, stringsAsFactors = FALSE)
}
structure(.Data = out, class = c("bug_drug_combinations", x_class))
set_clean_class(out,
new_class = c("bug_drug_combinations", x_class))
}
#' @method format bug_drug_combinations
@@ -121,6 +126,17 @@ format.bug_drug_combinations <- function(x,
decimal.mark = getOption("OutDec"),
big.mark = ifelse(decimal.mark == ",", ".", ","),
...) {
meet_criteria(x, allow_class = "data.frame")
meet_criteria(translate_ab, allow_class = c("character", "logical"), has_length = 1, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(minimum, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(combine_SI, allow_class = "logical", has_length = 1)
meet_criteria(combine_IR, allow_class = "logical", has_length = 1)
meet_criteria(add_ab_group, allow_class = "logical", has_length = 1)
meet_criteria(remove_intrinsic_resistant, allow_class = "logical", has_length = 1)
meet_criteria(decimal.mark, allow_class = "character", has_length = 1)
meet_criteria(big.mark, allow_class = "character", has_length = 1)
x <- as.data.frame(x, stringsAsFactors = FALSE)
x <- subset(x, total >= minimum)
@@ -151,7 +167,8 @@ format.bug_drug_combinations <- function(x,
remove_NAs <- function(.data) {
cols <- colnames(.data)
.data <- as.data.frame(sapply(.data, function(x) ifelse(is.na(x), "", x), simplify = FALSE))
.data <- as.data.frame(lapply(.data, function(x) ifelse(is.na(x), "", x)),
stringsAsFactors = FALSE)
colnames(.data) <- cols
.data
}
@@ -220,7 +237,7 @@ format.bug_drug_combinations <- function(x,
}
if (remove_intrinsic_resistant == TRUE) {
y <- y[, !sapply(y, function(col) all(col %like% "100", na.rm = TRUE) & !any(is.na(col))), drop = FALSE]
y <- y[, !vapply(FUN.VALUE = logical(1), y, function(col) all(col %like% "100", na.rm = TRUE) & !any(is.na(col))), drop = FALSE]
}
rownames(y) <- NULL
@@ -231,7 +248,8 @@ format.bug_drug_combinations <- function(x,
#' @export
print.bug_drug_combinations <- function(x, ...) {
x_class <- class(x)
print(structure(x, class = x_class[x_class != "bug_drug_combinations"]),
print(set_clean_class(x,
new_class = x_class[x_class != "bug_drug_combinations"]),
...)
message(font_blue("NOTE: Use 'format()' on this result to get a publishable/printable format."))
message_("Use 'format()' on this result to get a publishable/printable format.", as_note = FALSE)
}
+38 -22
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,30 +20,46 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
format_included_data_number <- function(data) {
if (is.data.frame(data)) {
n <- nrow(data)
} else {
n <- length(unique(data))
}
if (n > 10000) {
rounder <- -3 # round on thousands
} else if (n > 1000) {
rounder <- -2 # round on hundreds
} else {
rounder <- -1 # round on tens
}
paste0("~", format(round(n, rounder), decimal.mark = ".", big.mark = ","))
}
#' The Catalogue of Life
#'
#' This package contains the complete taxonomic tree of almost all microorganisms from the authoritative and comprehensive Catalogue of Life.
#' @section Catalogue of Life:
#' \if{html}{\figure{logo_col.png}{options: height=40px style=margin-bottom:5px} \cr}
#' This package contains the complete taxonomic tree of almost all microorganisms (~70,000 species) from the authoritative and comprehensive Catalogue of Life (<http://www.catalogueoflife.org>). The Catalogue of Life is the most comprehensive and authoritative global index of species currently available.
#' This package contains the complete taxonomic tree of almost all microorganisms (~70,000 species) from the authoritative and comprehensive Catalogue of Life (CoL, <http://www.catalogueoflife.org>). The CoL is the most comprehensive and authoritative global index of species currently available. Nonetheless, we supplemented the CoL data with data from the List of Prokaryotic names with Standing in Nomenclature (LPSN, [lpsn.dsmz.de](https://lpsn.dsmz.de)). This supplementation is needed until the [CoL+ project](https://github.com/CatalogueOfLife/general) is finished, which we await.
#'
#' [Click here][catalogue_of_life] for more information about the included taxa. Check which version of the Catalogue of Life was included in this package with [catalogue_of_life_version()].
#' @section Included taxa:
#' [Click here][catalogue_of_life] for more information about the included taxa. Check which versions of the CoL and LSPN were included in this package with [catalogue_of_life_version()].
#' @section Included Taxa:
#' Included are:
#' - All ~61,000 (sub)species from the kingdoms of Archaea, Bacteria, Chromista and Protozoa
#' - All ~8,500 (sub)species from these orders of the kingdom of Fungi: Eurotiales, Microascales, Mucorales, Onygenales, Pneumocystales, Saccharomycetales, Schizosaccharomycetales and Tremellales. The kingdom of Fungi is a very large taxon with almost 300,000 different (sub)species, of which most are not microbial (but rather macroscopic, like mushrooms). Because of this, not all fungi fit the scope of this package and including everything would tremendously slow down our algorithms too. By only including the aforementioned taxonomic orders, the most relevant fungi are covered (like all species of *Aspergillus*, *Candida*, *Cryptococcus*, *Histplasma*, *Pneumocystis*, *Saccharomyces* and *Trichophyton*).
#' - All ~150 (sub)species from ~100 other relevant genera from the kingdom of Animalia (like *Strongyloides* and *Taenia*)
#' - All ~23,000 previously accepted names of all included (sub)species (these were taxonomically renamed)
#' - All `r format_included_data_number(microorganisms[which(microorganisms$kingdom %in% c("Archeae", "Bacteria", "Chromista", "Protozoa")), ])` (sub)species from the kingdoms of Archaea, Bacteria, Chromista and Protozoa
#' - All `r format_included_data_number(microorganisms[which(microorganisms$kingdom == "Fungi" & microorganisms$order %in% c("Eurotiales", "Microascales", "Mucorales", "Onygenales", "Pneumocystales", "Saccharomycetales", "Schizosaccharomycetales", "Tremellales")), ])` (sub)species from these orders of the kingdom of Fungi: Eurotiales, Microascales, Mucorales, Onygenales, Pneumocystales, Saccharomycetales, Schizosaccharomycetales and Tremellales, as well as `r format_included_data_number(microorganisms[which(microorganisms$kingdom == "Fungi" & !microorganisms$order %in% c("Eurotiales", "Microascales", "Mucorales", "Onygenales", "Pneumocystales", "Saccharomycetales", "Schizosaccharomycetales", "Tremellales")), ])` other fungal (sub)species. The kingdom of Fungi is a very large taxon with almost 300,000 different (sub)species, of which most are not microbial (but rather macroscopic, like mushrooms). Because of this, not all fungi fit the scope of this package and including everything would tremendously slow down our algorithms too. By only including the aforementioned taxonomic orders, the most relevant fungi are covered (such as all species of *Aspergillus*, *Candida*, *Cryptococcus*, *Histplasma*, *Pneumocystis*, *Saccharomyces* and *Trichophyton*).
#' - All `r format_included_data_number(microorganisms[which(microorganisms$kingdom == "Animalia"), ])` (sub)species from `r format_included_data_number(microorganisms[which(microorganisms$kingdom == "Animalia"), "genus"])` other relevant genera from the kingdom of Animalia (such as *Strongyloides* and *Taenia*)
#' - All `r format_included_data_number(microorganisms.old)` previously accepted names of all included (sub)species (these were taxonomically renamed)
#' - The complete taxonomic tree of all included (sub)species: from kingdom to subspecies
#' - The responsible author(s) and year of scientific publication
#'
#' The Catalogue of Life (<http://www.catalogueoflife.org>) is the most comprehensive and authoritative global index of species currently available. It holds essential information on the names, relationships and distributions of over 1.9 million species. The Catalogue of Life is used to support the major biodiversity and conservation information services such as the Global Biodiversity Information Facility (GBIF), Encyclopedia of Life (EoL) and the International Union for Conservation of Nature Red List. It is recognised by the Convention on Biological Diversity as a significant component of the Global Taxonomy Initiative and a contribution to Target 1 of the Global Strategy for Plant Conservation.
#'
#' The syntax used to transform the original data to a cleansed R format, can be found here: <https://github.com/msberends/AMR/blob/master/data-raw/reproduction_of_microorganisms.R>.
#' @inheritSection AMR Read more on our website!
#' The syntax used to transform the original data to a cleansed \R format, can be found here: <https://github.com/msberends/AMR/blob/master/data-raw/reproduction_of_microorganisms.R>.
#' @inheritSection AMR Read more on Our Website!
#' @name catalogue_of_life
#' @rdname catalogue_of_life
#' @seealso Data set [microorganisms] for the actual data. \cr
@@ -57,26 +73,26 @@
#' mo_shortname("Chlamydophila psittaci")
#' # Note: 'Chlamydophila psittaci' (Everett et al., 1999) was renamed back to
#' # 'Chlamydia psittaci' (Page, 1968)
#' # [1] "C. psittaci"
#' #> [1] "C. psittaci"
#'
#' # Get any property from the entire taxonomic tree for all included species
#' mo_class("E. coli")
#' # [1] "Gammaproteobacteria"
#' #> [1] "Gammaproteobacteria"
#'
#' mo_family("E. coli")
#' # [1] "Enterobacteriaceae"
#' #> [1] "Enterobacteriaceae"
#'
#' mo_gramstain("E. coli") # based on kingdom and phylum, see ?mo_gramstain
#' # [1] "Gram negative"
#' #> [1] "Gram-negative"
#'
#' mo_ref("E. coli")
#' # [1] "Castellani et al., 1919"
#' #> [1] "Castellani et al., 1919"
#'
#' # Do not get mistaken - this package is about microorganisms
#' mo_kingdom("C. elegans")
#' # [1] "Fungi" # Fungi?!
#' #> [1] "Fungi" # Fungi?!
#' mo_name("C. elegans")
#' # [1] "Cladosporium elegans" # Because a microorganism was found
#' #> [1] "Cladosporium elegans" # Because a microorganism was found
NULL
#' Version info of included Catalogue of Life
@@ -86,7 +102,7 @@ NULL
#' @details For DSMZ, see [microorganisms].
#' @return a [list], which prints in pretty format
#' @inheritSection catalogue_of_life Catalogue of Life
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @export
catalogue_of_life_version <- function() {
@@ -107,8 +123,8 @@ catalogue_of_life_version <- function() {
n_total_species = nrow(microorganisms),
n_total_synonyms = nrow(microorganisms.old)))
structure(.Data = lst,
class = c("catalogue_of_life_version", "list"))
set_clean_class(lst,
new_class = c("catalogue_of_life_version", "list"))
}
#' @method print catalogue_of_life_version
+16 -11
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,15 +20,15 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Count available isolates
#' Count Available Isolates
#'
#' @description These functions can be used to count resistant/susceptible microbial isolates. All functions support quasiquotation with pipes, can be used in `summarise()` from the `dplyr` package and also support grouped variables, please see *Examples*.
#' @description These functions can be used to count resistant/susceptible microbial isolates. All functions support quasiquotation with pipes, can be used in `summarise()` from the `dplyr` package and also support grouped variables, see *Examples*.
#'
#' [count_resistant()] should be used to count resistant isolates, [count_susceptible()] should be used to count susceptible isolates.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param ... one or more vectors (or columns) with antibiotic interpretations. They will be transformed internally with [as.rsi()] if needed.
#' @inheritParams proportion
#' @inheritSection as.rsi Interpretation of R and S/I
@@ -39,13 +39,13 @@
#' The function [n_rsi()] is an alias of [count_all()]. They can be used to count all available isolates, i.e. where all input antibiotics have an available result (S, I or R). Their use is equal to `n_distinct()`. Their function is equal to `count_susceptible(...) + count_resistant(...)`.
#'
#' The function [count_df()] takes any variable from `data` that has an [`rsi`] class (created with [as.rsi()]) and counts the number of S's, I's and R's. It also supports grouped variables. The function [rsi_df()] works exactly like [count_df()], but adds the percentage of S, I and R.
#' @inheritSection proportion Combination therapy
#' @inheritSection proportion Combination Therapy
#' @seealso [`proportion_*`][proportion] to calculate microbial resistance and susceptibility.
#' @return An [integer]
#' @rdname count
#' @name count
#' @export
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # example_isolates is a data set available in the AMR package.
#' ?example_isolates
@@ -134,7 +134,10 @@ count_R <- function(..., only_all_tested = FALSE) {
#' @rdname count
#' @export
count_IR <- function(..., only_all_tested = FALSE) {
warning("Using 'count_IR' is discouraged; use 'count_resistant()' instead to not consider \"I\" being resistant.", call. = FALSE)
if (message_not_thrown_before("count_IR")) {
warning_("Using count_IR() is discouraged; use count_resistant() instead to not consider \"I\" being resistant.", call = FALSE)
remember_thrown_message("count_IR")
}
rsi_calc(...,
ab_result = c("I", "R"),
only_all_tested = only_all_tested,
@@ -162,7 +165,10 @@ count_SI <- function(..., only_all_tested = FALSE) {
#' @rdname count
#' @export
count_S <- function(..., only_all_tested = FALSE) {
warning("Using 'count_S' is discouraged; use 'count_susceptible()' instead to also consider \"I\" being susceptible.", call. = FALSE)
if (message_not_thrown_before("count_S")) {
warning_("Using count_S() is discouraged; use count_susceptible() instead to also consider \"I\" being susceptible.", call = FALSE)
remember_thrown_message("count_S")
}
rsi_calc(...,
ab_result = "S",
only_all_tested = only_all_tested,
@@ -189,7 +195,6 @@ count_df <- function(data,
language = get_locale(),
combine_SI = TRUE,
combine_IR = FALSE) {
rsi_calc_df(type = "count",
data = data,
translate_ab = translate_ab,
+75 -50
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,15 +20,15 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Data sets with `r format(nrow(antibiotics) + nrow(antivirals), big.mark = ",")` antimicrobials
#' Data Sets with `r format(nrow(antibiotics) + nrow(antivirals), big.mark = ",")` Antimicrobials
#'
#' Two data sets containing all antibiotics/antimycotics and antivirals. Use [as.ab()] or one of the [ab_property()] functions to retrieve values from the [antibiotics] data set. Three identifiers are included in this data set: an antibiotic ID (`ab`, primarily used in this package) as defined by WHONET/EARS-Net, an ATC code (`atc`) as defined by the WHO, and a Compound ID (`cid`) as found in PubChem. Other properties in this data set are derived from one or more of these codes.
#' Two data sets containing all antibiotics/antimycotics and antivirals. Use [as.ab()] or one of the [`ab_*`][ab_property()] functions to retrieve values from the [antibiotics] data set. Three identifiers are included in this data set: an antibiotic ID (`ab`, primarily used in this package) as defined by WHONET/EARS-Net, an ATC code (`atc`) as defined by the WHO, and a Compound ID (`cid`) as found in PubChem. Other properties in this data set are derived from one or more of these codes.
#' @format
#' ### For the [antibiotics] data set: a [data.frame] with `r nrow(antibiotics)` observations and `r ncol(antibiotics)` variables:
#' - `ab`\cr Antibiotic ID as used in this package (like `AMC`), using the official EARS-Net (European Antimicrobial Resistance Surveillance Network) codes where available
#' ## For the [antibiotics] data set: a [data.frame] with `r nrow(antibiotics)` observations and `r ncol(antibiotics)` variables:
#' - `ab`\cr Antibiotic ID as used in this package (such as `AMC`), using the official EARS-Net (European Antimicrobial Resistance Surveillance Network) codes where available
#' - `atc`\cr ATC code (Anatomical Therapeutic Chemical) as defined by the WHOCC, like `J01CR02`
#' - `cid`\cr Compound ID as found in PubChem
#' - `name`\cr Official name as used by WHONET/EARS-Net or the WHO
@@ -43,7 +43,7 @@
#' - `iv_units`\cr Units of `iv_ddd`
#' - `loinc`\cr All LOINC codes (Logical Observation Identifiers Names and Codes) associated with the name of the antimicrobial agent. Use [ab_loinc()] to retrieve them quickly, see [ab_property()].
#'
#' ### For the [antivirals] data set: a [data.frame] with `r nrow(antivirals)` observations and `r ncol(antivirals)` variables:
#' ## For the [antivirals] data set: a [data.frame] with `r nrow(antivirals)` observations and `r ncol(antivirals)` variables:
#' - `atc`\cr ATC code (Anatomical Therapeutic Chemical) as defined by the WHOCC
#' - `cid`\cr Compound ID as found in PubChem
#' - `name`\cr Official name as used by WHONET/EARS-Net or the WHO
@@ -57,13 +57,13 @@
#'
#' Synonyms (i.e. trade names) are derived from the Compound ID (`cid`) and consequently only available where a CID is available.
#'
#' ### Direct download
#' These data sets are available as 'flat files' for use even without R - you can find the files here:
#' ## Direct download
#' These data sets are available as 'flat files' for use even without \R - you can find the files here:
#'
#' * <https://github.com/msberends/AMR/raw/master/data-raw/antibiotics.txt>
#' * <https://github.com/msberends/AMR/raw/master/data-raw/antivirals.txt>
#'
#' Files in R format (with preserved data structure) can be found here:
#' Files in \R format (with preserved data structure) can be found here:
#'
#' * <https://github.com/msberends/AMR/raw/master/data/antibiotics.rda>
#' * <https://github.com/msberends/AMR/raw/master/data/antivirals.rda>
@@ -72,16 +72,16 @@
#' WHONET 2019 software: <http://www.whonet.org/software.html>
#'
#' European Commission Public Health PHARMACEUTICALS - COMMUNITY REGISTER: <http://ec.europa.eu/health/documents/community-register/html/atc.htm>
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection WHOCC WHOCC
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @seealso [microorganisms], [intrinsic_resistant]
"antibiotics"
#' @rdname antibiotics
"antivirals"
#' Data set with `r format(nrow(microorganisms), big.mark = ",")` microorganisms
#' Data Set with `r format(nrow(microorganisms), big.mark = ",")` Microorganisms
#'
#' A data set containing the microbial taxonomy of six kingdoms from the Catalogue of Life. MO codes can be looked up using [as.mo()].
#' @inheritSection catalogue_of_life Catalogue of Life
@@ -92,10 +92,17 @@
#' - `rank`\cr Text of the taxonomic rank of the microorganism, like `"species"` or `"genus"`
#' - `ref`\cr Author(s) and year of concerning scientific publication
#' - `species_id`\cr ID of the species as used by the Catalogue of Life
#' - `source`\cr Either "CoL", "DSMZ" (see Source) or "manually added"
#' - `source`\cr Either "CoL", "DSMZ" (see *Source*) or "manually added"
#' - `prevalence`\cr Prevalence of the microorganism, see [as.mo()]
#' - `snomed`\cr SNOMED code of the microorganism. Use [mo_snomed()] to retrieve it quickly, see [mo_property()].
#' @details Manually added were:
#' @details
#' Please note that entries are only based on the Catalogue of Life and the LPSN (see below). Since these sources incorporate entries based on (recent) publications in the International Journal of Systematic and Evolutionary Microbiology (IJSEM), it can happen that the year of publication is sometimes later than one might expect.
#'
#' For example, *Staphylococcus pettenkoferi* was newly named in Diagnostic Microbiology and Infectious Disease in 2002 (PMID 12106949), but it was not before 2007 that a publication in IJSEM followed (PMID 17625191). Consequently, the AMR package returns 2007 for `mo_year("S. pettenkoferi")`.
#'
#' ## Manually additions
#' For convenience, some entries were added manually:
#'
#' - 11 entries of *Streptococcus* (beta-haemolytic: groups A, B, C, D, F, G, H, K and unspecified; other: viridans, milleri)
#' - 2 entries of *Staphylococcus* (coagulase-negative (CoNS) and coagulase-positive (CoPS))
#' - 3 entries of *Trichomonas* (*Trichomonas vaginalis*, and its family and genus)
@@ -105,26 +112,26 @@
#' - 6 families under the Enterobacterales order, according to Adeolu *et al.* (2016, PMID 27620848), that are not (yet) in the Catalogue of Life
#' - `r format(nrow(subset(microorganisms, source == "DSMZ")), big.mark = ",")` species from the DSMZ (Deutsche Sammlung von Mikroorganismen und Zellkulturen) since the DSMZ contain the latest taxonomic information based on recent publications
#'
#' ### Direct download
#' This data set is available as 'flat file' for use even without R - you can find the file here:
#' ## Direct download
#' This data set is available as 'flat file' for use even without \R - you can find the file here:
#'
#' * <https://github.com/msberends/AMR/raw/master/data-raw/microorganisms.txt>
#'
#' The file in R format (with preserved data structure) can be found here:
#' The file in \R format (with preserved data structure) can be found here:
#'
#' * <https://github.com/msberends/AMR/raw/master/data/microorganisms.rda>
#' @section About the records from DSMZ (see source):
#' @section About the Records from DSMZ (see *Source*):
#' Names of prokaryotes are defined as being validly published by the International Code of Nomenclature of Bacteria. Validly published are all names which are included in the Approved Lists of Bacterial Names and the names subsequently published in the International Journal of Systematic Bacteriology (IJSB) and, from January 2000, in the International Journal of Systematic and Evolutionary Microbiology (IJSEM) as original articles or in the validation lists.
#' *(from <https://www.dsmz.de/services/online-tools/prokaryotic-nomenclature-up-to-date>)*
#'
#' In February 2020, the DSMZ records were merged with the List of Prokaryotic names with Standing in Nomenclature (LPSN).
#' @source Catalogue of Life: Annual Checklist (public online taxonomic database), <http://www.catalogueoflife.org> (check included annual version with [catalogue_of_life_version()]).
#'
#' Parte, A.C. (2018). LPSN — List of Prokaryotic names with Standing in Nomenclature (bacterio.net), 20 years on. International Journal of Systematic and Evolutionary Microbiology, 68, 1825-1829; doi: 10.1099/ijsem.0.002786
#' Parte, A.C. (2018). LPSN — List of Prokaryotic names with Standing in Nomenclature (bacterio.net), 20 years on. International Journal of Systematic and Evolutionary Microbiology, 68, 1825-1829; \doi{10.1099/ijsem.0.002786}
#'
#' Leibniz Institute DSMZ-German Collection of Microorganisms and Cell Cultures, Germany, Prokaryotic Nomenclature Up-to-Date, <https://www.dsmz.de/services/online-tools/prokaryotic-nomenclature-up-to-date> and <https://lpsn.dsmz.de> (check included version with [catalogue_of_life_version()]).
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @seealso [as.mo()], [mo_property()], [microorganisms.codes], [intrinsic_resistant]
"microorganisms"
@@ -136,7 +143,7 @@ catalogue_of_life <- list(
yearmonth_DSMZ = "May 2020"
)
#' Data set with previously accepted taxonomic names
#' Data Set with Previously Accepted Taxonomic Names
#'
#' A data set containing old (previously valid or accepted) taxonomic names according to the Catalogue of Life. This data set is used internally by [as.mo()].
#' @inheritSection catalogue_of_life Catalogue of Life
@@ -147,27 +154,27 @@ catalogue_of_life <- list(
#' - `prevalence`\cr Prevalence of the microorganism, see [as.mo()]
#' @source Catalogue of Life: Annual Checklist (public online taxonomic database), <http://www.catalogueoflife.org> (check included annual version with [catalogue_of_life_version()]).
#'
#' Parte, A.C. (2018). LPSN — List of Prokaryotic names with Standing in Nomenclature (bacterio.net), 20 years on. International Journal of Systematic and Evolutionary Microbiology, 68, 1825-1829; doi: 10.1099/ijsem.0.002786
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' Parte, A.C. (2018). LPSN — List of Prokaryotic names with Standing in Nomenclature (bacterio.net), 20 years on. International Journal of Systematic and Evolutionary Microbiology, 68, 1825-1829; \doi{10.1099/ijsem.0.002786}
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @seealso [as.mo()] [mo_property()] [microorganisms]
"microorganisms.old"
#' Data set with `r format(nrow(microorganisms.codes), big.mark = ",")` common microorganism codes
#' Data Set with `r format(nrow(microorganisms.codes), big.mark = ",")` Common Microorganism Codes
#'
#' A data set containing commonly used codes for microorganisms, from laboratory systems and WHONET. Define your own with [set_mo_source()]. They will all be searched when using [as.mo()] and consequently all the [`mo_*`][mo_property()] functions.
#' @format A [data.frame] with `r format(nrow(microorganisms.codes), big.mark = ",")` observations and `r ncol(microorganisms.codes)` variables:
#' - `code`\cr Commonly used code of a microorganism
#' - `mo`\cr ID of the microorganism in the [microorganisms] data set
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection catalogue_of_life Catalogue of Life
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @seealso [as.mo()] [microorganisms]
"microorganisms.codes"
#' Data set with `r format(nrow(example_isolates), big.mark = ",")` example isolates
#' Data Set with `r format(nrow(example_isolates), big.mark = ",")` Example Isolates
#'
#' A data set containing `r format(nrow(example_isolates), big.mark = ",")` microbial isolates with their full antibiograms. The data set reflects reality and can be used to practice AMR analysis. For examples, please read [the tutorial on our website](https://msberends.github.io/AMR/articles/AMR.html).
#' A data set containing `r format(nrow(example_isolates), big.mark = ",")` microbial isolates with their full antibiograms. The data set reflects reality and can be used to practice AMR data analysis. For examples, please read [the tutorial on our website](https://msberends.github.io/AMR/articles/AMR.html).
#' @format A [data.frame] with `r format(nrow(example_isolates), big.mark = ",")` observations and `r ncol(example_isolates)` variables:
#' - `date`\cr date of receipt at the laboratory
#' - `hospital_id`\cr ID of the hospital, from A to D
@@ -178,25 +185,25 @@ catalogue_of_life <- list(
#' - `gender`\cr gender of the patient
#' - `patient_id`\cr ID of the patient
#' - `mo`\cr ID of microorganism created with [as.mo()], see also [microorganisms]
#' - `PEN:RIF`\cr `r sum(sapply(example_isolates, is.rsi))` different antibiotics with class [`rsi`] (see [as.rsi()]); these column names occur in the [antibiotics] data set and can be translated with [ab_name()]
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' - `PEN:RIF`\cr `r sum(vapply(FUN.VALUE = logical(1), example_isolates, is.rsi))` different antibiotics with class [`rsi`] (see [as.rsi()]); these column names occur in the [antibiotics] data set and can be translated with [ab_name()]
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
"example_isolates"
#' Data set with unclean data
#' Data Set with Unclean Data
#'
#' A data set containing `r format(nrow(example_isolates_unclean), big.mark = ",")` microbial isolates that are not cleaned up and consequently not ready for AMR analysis. This data set can be used for practice.
#' A data set containing `r format(nrow(example_isolates_unclean), big.mark = ",")` microbial isolates that are not cleaned up and consequently not ready for AMR data analysis. This data set can be used for practice.
#' @format A [data.frame] with `r format(nrow(example_isolates_unclean), big.mark = ",")` observations and `r ncol(example_isolates_unclean)` variables:
#' - `patient_id`\cr ID of the patient
#' - `date`\cr date of receipt at the laboratory
#' - `hospital`\cr ID of the hospital, from A to C
#' - `bacteria`\cr info about microorganism that can be transformed with [as.mo()], see also [microorganisms]
#' - `AMX:GEN`\cr 4 different antibiotics that have to be transformed with [as.rsi()]
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
"example_isolates_unclean"
#' Data set with `r format(nrow(WHONET), big.mark = ",")` isolates - WHONET example
#' Data Set with `r format(nrow(WHONET), big.mark = ",")` Isolates - WHONET Example
#'
#' This example data set has the exact same structure as an export file from WHONET. Such files can be used with this package, as this example data set shows. The antibiotic results are from our [example_isolates] data set. All patient names are created using online surname generators and are only in place for practice purposes.
#' @format A [data.frame] with `r format(nrow(WHONET), big.mark = ",")` observations and `r ncol(WHONET)` variables:
@@ -225,12 +232,12 @@ catalogue_of_life <- list(
#' - `Inducible clindamycin resistance`\cr Clindamycin can be induced?
#' - `Comment`\cr Other comments
#' - `Date of data entry`\cr Date this data was entered in WHONET
#' - `AMP_ND10:CIP_EE`\cr `r sum(sapply(WHONET, is.rsi))` different antibiotics. You can lookup the abbreviations in the [antibiotics] data set, or use e.g. [`ab_name("AMP")`][ab_name()] to get the official name immediately. Before analysis, you should transform this to a valid antibiotic class, using [as.rsi()].
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' - `AMP_ND10:CIP_EE`\cr `r sum(vapply(FUN.VALUE = logical(1), WHONET, is.rsi))` different antibiotics. You can lookup the abbreviations in the [antibiotics] data set, or use e.g. [`ab_name("AMP")`][ab_name()] to get the official name immediately. Before analysis, you should transform this to a valid antibiotic class, using [as.rsi()].
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
"WHONET"
#' Data set for R/SI interpretation
#' Data Set for R/SI Interpretation
#'
#' Data set to interpret MIC and disk diffusion to R/SI values. Included guidelines are CLSI (`r min(as.integer(gsub("[^0-9]", "", subset(rsi_translation, guideline %like% "CLSI")$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(rsi_translation, guideline %like% "CLSI")$guideline)))`) and EUCAST (`r min(as.integer(gsub("[^0-9]", "", subset(rsi_translation, guideline %like% "EUCAST")$guideline)))`-`r max(as.integer(gsub("[^0-9]", "", subset(rsi_translation, guideline %like% "EUCAST")$guideline)))`). Use [as.rsi()] to transform MICs or disks measurements to R/SI values.
#' @format A [data.frame] with `r format(nrow(rsi_translation), big.mark = ",")` observations and `r ncol(rsi_translation)` variables:
@@ -245,12 +252,12 @@ catalogue_of_life <- list(
#' - `breakpoint_R`\cr Highest MIC value or lowest number of millimetres that leads to "R"
#' - `uti`\cr A logical value (`TRUE`/`FALSE`) to indicate whether the rule applies to a urinary tract infection (UTI)
#' @details The repository of this `AMR` package contains a file comprising this exact data set: <https://github.com/msberends/AMR/blob/master/data-raw/rsi_translation.txt>. This file **allows for machine reading EUCAST and CLSI guidelines**, which is almost impossible with the Excel and PDF files distributed by EUCAST and CLSI. The file is updated automatically.
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @seealso [intrinsic_resistant]
"rsi_translation"
#' Data set with bacterial intrinsic resistance
#' Data Set with Bacterial Intrinsic Resistance
#'
#' Data set containing defined intrinsic resistance by EUCAST of all bug-drug combinations.
#' @format A [data.frame] with `r format(nrow(intrinsic_resistant), big.mark = ",")` observations and `r ncol(intrinsic_resistant)` variables:
@@ -258,9 +265,9 @@ catalogue_of_life <- list(
#' - `antibiotic`\cr Name of the antibiotic drug
#' @details The repository of this `AMR` package contains a file comprising this exact data set: <https://github.com/msberends/AMR/blob/master/data-raw/intrinsic_resistant.txt>. This file **allows for machine reading EUCAST guidelines about intrinsic resistance**, which is almost impossible with the Excel and PDF files distributed by EUCAST. The file is updated automatically.
#'
#' This data set is based on '`r EUCAST_VERSION_EXPERT_RULES[["3.2"]]$title`', `r EUCAST_VERSION_EXPERT_RULES[["3.2"]]$version_txt` from `r EUCAST_VERSION_EXPERT_RULES[["3.2"]]$year`.
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' This data set is based on `r format_eucast_version_nr(3.2)`.
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' if (require("dplyr")) {
#' intrinsic_resistant %>%
@@ -269,3 +276,21 @@ catalogue_of_life <- list(
#' # [1] "Enterococcus casseliflavus" "Enterococcus gallinarum"
#' }
"intrinsic_resistant"
#' Data Set with Treatment Dosages as Defined by EUCAST
#'
#' EUCAST breakpoints used in this package are based on the dosages in this data set. They can be retrieved with [eucast_dosage()].
#' @format A [data.frame] with `r format(nrow(dosage), big.mark = ",")` observations and `r ncol(dosage)` variables:
#' - `ab`\cr Antibiotic ID as used in this package (such as `AMC`), using the official EARS-Net (European Antimicrobial Resistance Surveillance Network) codes where available
#' - `name`\cr Official name of the antimicrobial agent as used by WHONET/EARS-Net or the WHO
#' - `type`\cr Type of the dosage, either `r vector_or(dosage$type)`
#' - `dose`\cr Dose, such as "2 g" or "25 mg/kg"
#' - `dose_times`\cr Number of times a dose must be administered
#' - `administration`\cr Route of administration, either `r vector_or(dosage$administration)`
#' - `notes`\cr Additional dosage notes
#' - `original_txt`\cr Original text in the PDF file of EUCAST
#' - `eucast_version`\cr Version number of the EUCAST Clinical Breakpoints guideline to which these dosages apply
#' @details `r format_eucast_version_nr(11.0)` are based on the dosages in this data set.
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
"dosage"
+21 -7
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,14 +20,28 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Deprecated functions
#' Deprecated Functions
#'
#' These functions are so-called '[Deprecated]'. They will be removed in a future release. Using the functions will give a warning with the name of the function it has been replaced by (if there is one).
#' @inheritSection lifecycle Retired lifecycle
#' @inheritSection AMR Read more on our website!
#' @inheritSection lifecycle Retired Lifecycle
#' @inheritSection AMR Read more on Our Website!
#' @keywords internal
#' @name AMR-deprecated
# @export
#' @export
p_symbol <- function(p, emptychar = " ") {
.Deprecated(package = "AMR", new = "cleaner::p_symbol")
p <- as.double(p)
s <- rep(NA_character_, length(p))
s[p <= 1] <- emptychar
s[p <= 0.100] <- "."
s[p <= 0.050] <- "*"
s[p <= 0.010] <- "**"
s[p <= 0.001] <- "***"
s
}
+52 -24
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,13 +20,13 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Transform input to disk diffusion diameters
#' Transform Input to Disk Diffusion Diameters
#'
#' This transforms a vector to a new class [`disk`], which is a disk diffusion growth zone size (around an antibiotic disk) in millimetres between 6 and 50.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @rdname as.disk
#' @param x vector
#' @param na.rm a logical indicating whether missing values should be removed
@@ -35,11 +35,10 @@
#' @aliases disk
#' @export
#' @seealso [as.rsi()]
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' \donttest{
#' # transform existing disk zones to the `disk` class
#' library(dplyr)
#' df <- data.frame(microorganism = "E. coli",
#' AMP = 20,
#' CIP = 14,
@@ -58,8 +57,11 @@
#' as.rsi(df)
#' }
as.disk <- function(x, na.rm = FALSE) {
meet_criteria(x, allow_class = c("disk", "character", "numeric", "integer"), allow_NA = TRUE)
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
if (!is.disk(x)) {
x <- x %pm>% unlist()
x <- unlist(x)
if (na.rm == TRUE) {
x <- x[!is.na(x)]
}
@@ -67,13 +69,13 @@ as.disk <- function(x, na.rm = FALSE) {
na_before <- length(x[is.na(x)])
# heavily based on the function from our cleaner package:
# heavily based on cleaner::clean_double():
clean_double2 <- function(x, remove = "[^0-9.,-]", fixed = FALSE) {
x <- gsub(",", ".", x)
# remove ending dot/comma
x <- gsub("[,.]$", "", x)
# only keep last dot/comma
reverse <- function(x) sapply(lapply(strsplit(x, NULL), rev), paste, collapse = "")
reverse <- function(x) vapply(FUN.VALUE = character(1), lapply(strsplit(x, NULL), rev), paste, collapse = "")
x <- sub("{{dot}}", ".",
gsub(".", "",
reverse(sub(".", "}}tod{{",
@@ -96,21 +98,25 @@ as.disk <- function(x, na.rm = FALSE) {
if (na_before != na_after) {
list_missing <- x.bak[is.na(x) & !is.na(x.bak)] %pm>%
unique() %pm>%
sort()
list_missing <- paste0('"', list_missing, '"', collapse = ", ")
warning(na_after - na_before, " results truncated (",
round(((na_after - na_before) / length(x)) * 100),
"%) that were invalid disk zones: ",
list_missing, call. = FALSE)
sort() %pm>%
vector_and(quotes = TRUE)
warning_(na_after - na_before, " results truncated (",
round(((na_after - na_before) / length(x)) * 100),
"%) that were invalid disk zones: ",
list_missing, call = FALSE)
}
}
structure(as.integer(x),
class = c("disk", "integer"))
set_clean_class(as.integer(x),
new_class = c("disk", "integer"))
}
all_valid_disks <- function(x) {
x_disk <- suppressWarnings(as.disk(x[!is.na(x)]))
!any(is.na(x_disk)) & !all(is.na(x))
if (!inherits(x, c("disk", "character", "numeric", "integer"))) {
return(FALSE)
}
x_disk <- tryCatch(suppressWarnings(as.disk(x[!is.na(x)])),
error = function(e) NA)
!any(is.na(x_disk)) && !all(is.na(x))
}
#' @rdname as.disk
@@ -139,6 +145,30 @@ print.disk <- function(x, ...) {
print(as.integer(x), quote = FALSE)
}
#' @method plot disk
#' @export
#' @importFrom graphics barplot axis
#' @rdname plot
plot.disk <- function(x,
main = paste("Disk zones values of", deparse(substitute(x))),
ylab = "Frequency",
xlab = "Disk diffusion (mm)",
axes = FALSE,
...) {
meet_criteria(main, allow_class = "character", has_length = 1)
meet_criteria(ylab, allow_class = "character", has_length = 1)
meet_criteria(xlab, allow_class = "character", has_length = 1)
meet_criteria(axes, allow_class = "logical", has_length = 1)
barplot(table(x),
ylab = ylab,
xlab = xlab,
axes = axes,
main = main,
...)
axis(2, seq(0, max(table(x))))
}
#' @method [ disk
#' @export
#' @noRd
@@ -194,14 +224,12 @@ unique.disk <- function(x, incomparables = FALSE, ...) {
# will be exported using s3_register() in R/zzz.R
get_skimmers.disk <- function(column) {
sfl <- import_fn("sfl", "skimr", error_on_fail = FALSE)
inline_hist <- import_fn("inline_hist", "skimr", error_on_fail = FALSE)
sfl(
skimr::sfl(
skim_type = "disk",
min = ~min(as.double(.), na.rm = TRUE),
max = ~max(as.double(.), na.rm = TRUE),
median = ~stats::median(as.double(.), na.rm = TRUE),
n_unique = ~pm_n_distinct(., na.rm = TRUE),
hist = ~inline_hist(stats::na.omit(as.double(.)))
hist = ~skimr::inline_hist(stats::na.omit(as.double(.)))
)
}
+190
View File
@@ -0,0 +1,190 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
# GNU General Public License version 2.0 (GNU GPL-2), as published by #
# the Free Software Foundation. #
# We created this package for both routine data analysis and academic #
# research and it was publicly released in the hope that it will be #
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Determine (New) Episodes for Patients
#'
#' These functions determine which items in a vector can be considered (the start of) a new episode, based on the argument `episode_days`. This can be used to determine clinical episodes for any epidemiological analysis. The [get_episode()] function returns the index number of the episode per group, while the [is_new_episode()] function returns values `TRUE`/`FALSE` to indicate whether an item in a vector is the start of a new episode.
#' @inheritSection lifecycle Stable Lifecycle
#' @param x vector of dates (class `Date` or `POSIXt`)
#' @param episode_days required episode length in days, can also be less than a day, see *Details*
#' @param ... currently not used
#' @details
#' Dates are first sorted from old to new. The oldest date will mark the start of the first episode. After this date, the next date will be marked that is at least `episode_days` days later than the start of the first episode. From that second marked date on, the next date will be marked that is at least `episode_days` days later than the start of the second episode which will be the start of the third episode, and so on. Before the vector is being returned, the original order will be restored.
#'
#' The [first_isolate()] function is a wrapper around the [is_new_episode()] function, but is more efficient for data sets containing microorganism codes or names.
#'
#' The `dplyr` package is not required for these functions to work, but these functions support [variable grouping][dplyr::group_by()] and work conveniently inside `dplyr` verbs such as [`filter()`][dplyr::filter()], [`mutate()`][dplyr::mutate()] and [`summarise()`][dplyr::summarise()].
#' @return
#' * [get_episode()]: a [double] vector
#' * [is_new_episode()]: a [logical] vector
#' @seealso [first_isolate()]
#' @rdname get_episode
#' @export
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # `example_isolates` is a data set available in the AMR package.
#' # See ?example_isolates.
#'
#' get_episode(example_isolates$date, episode_days = 60) # indices
#' is_new_episode(example_isolates$date, episode_days = 60) # TRUE/FALSE
#'
#' # filter on results from the third 60-day episode only, using base R
#' example_isolates[which(get_episode(example_isolates$date, 60) == 3), ]
#'
#' # the functions also work for less than a day, e.g. to include one per hour:
#' get_episode(c(Sys.time(),
#' Sys.time() + 60 * 60),
#' episode_days = 1/24)
#'
#' \donttest{
#' if (require("dplyr")) {
#' # is_new_episode() can also be used in dplyr verbs to determine patient
#' # episodes based on any (combination of) grouping variables:
#' example_isolates %>%
#' mutate(condition = sample(x = c("A", "B", "C"),
#' size = 2000,
#' replace = TRUE)) %>%
#' group_by(condition) %>%
#' mutate(new_episode = is_new_episode(date, 365))
#'
#' example_isolates %>%
#' group_by(hospital_id, patient_id) %>%
#' transmute(date,
#' patient_id,
#' new_index = get_episode(date, 60),
#' new_logical = is_new_episode(date, 60))
#'
#'
#' example_isolates %>%
#' group_by(hospital_id) %>%
#' summarise(patients = n_distinct(patient_id),
#' n_episodes_365 = sum(is_new_episode(date, episode_days = 365)),
#' n_episodes_60 = sum(is_new_episode(date, episode_days = 60)),
#' n_episodes_30 = sum(is_new_episode(date, episode_days = 30)))
#'
#'
#' # grouping on patients and microorganisms leads to the same results
#' # as first_isolate():
#' x <- example_isolates %>%
#' filter(first_isolate(., include_unknown = TRUE))
#'
#' y <- example_isolates %>%
#' group_by(patient_id, mo) %>%
#' filter(is_new_episode(date, 365))
#'
#' identical(x$patient_id, y$patient_id)
#'
#' # but is_new_episode() has a lot more flexibility than first_isolate(),
#' # since you can now group on anything that seems relevant:
#' example_isolates %>%
#' group_by(patient_id, mo, hospital_id, ward_icu) %>%
#' mutate(flag_episode = is_new_episode(date, 365))
#' }
#' }
get_episode <- function(x, episode_days, ...) {
meet_criteria(x, allow_class = c("Date", "POSIXt"))
meet_criteria(episode_days, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
exec_episode(type = "sequential",
x = x,
episode_days = episode_days,
... = ...)
}
#' @rdname get_episode
#' @export
is_new_episode <- function(x, episode_days, ...) {
meet_criteria(x, allow_class = c("Date", "POSIXt"))
meet_criteria(episode_days, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
exec_episode(type = "logical",
x = x,
episode_days = episode_days,
... = ...)
}
exec_episode <- function(type, x, episode_days, ...) {
x <- as.double(as.POSIXct(x)) # as.POSIXct() for Date classes
# since x is now in seconds, get seconds from episode_days as well
episode_seconds <- episode_days * 60 * 60 * 24
if (length(x) == 1) {
if (type == "logical") {
return(TRUE)
} else if (type == "sequential") {
return(1)
}
} else if (length(x) == 2) {
if (max(x) - min(x) >= episode_seconds) {
if (type == "logical") {
return(c(TRUE, TRUE))
} else if (type == "sequential") {
return(c(1, 2))
}
} else {
if (type == "logical") {
return(c(TRUE, FALSE))
} else if (type == "sequential") {
return(c(1, 1))
}
}
}
# I asked on StackOverflow:
# https://stackoverflow.com/questions/42122245/filter-one-row-every-year
exec <- function(x, episode_seconds) {
indices <- integer()
start <- x[1]
ind <- 1
indices[1] <- 1
for (i in 2:length(x)) {
if (isTRUE((x[i] - start) >= episode_seconds)) {
ind <- ind + 1
if (type == "logical") {
indices[ind] <- i
}
start <- x[i]
}
if (type == "sequential") {
indices[i] <- ind
}
}
if (type == "logical") {
result <- rep(FALSE, length(x))
result[indices] <- TRUE
result
} else if (type == "sequential") {
indices
}
}
df <- data.frame(x = x,
y = seq_len(length(x))) %pm>%
pm_arrange(x)
df$new <- exec(df$x, episode_seconds)
df %pm>%
pm_arrange(y) %pm>%
pm_pull(new)
}
+230 -111
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,35 +20,65 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
# add new version numbers here, and add the rules themselves to "data-raw/eucast_rules.tsv"
# (running "data-raw/internals.R" will process that TSV file)
EUCAST_VERSION_BREAKPOINTS <- list("10.0" = list(version_txt = "v10.0",
# add new version numbers here, and add the rules themselves to "data-raw/eucast_rules.tsv" and rsi_translation
# (sourcing "data-raw/_internals.R" will process the TSV file)
EUCAST_VERSION_BREAKPOINTS <- list("11.0" = list(version_txt = "v11.0",
year = 2021,
title = "'EUCAST Clinical Breakpoint Tables'",
url = "https://www.eucast.org/clinical_breakpoints/"),
"10.0" = list(version_txt = "v10.0",
year = 2020,
title = "EUCAST Clinical Breakpoints"))
title = "'EUCAST Clinical Breakpoint Tables'",
url = "https://www.eucast.org/ast_of_bacteria/previous_versions_of_documents/"))
EUCAST_VERSION_EXPERT_RULES <- list("3.1" = list(version_txt = "v3.1",
year = 2016,
title = "EUCAST Expert Rules, Intrinsic Resistance and Exceptional Phenotypes"),
title = "'EUCAST Expert Rules, Intrinsic Resistance and Exceptional Phenotypes'",
url = "https://www.eucast.org/expert_rules_and_intrinsic_resistance/"),
"3.2" = list(version_txt = "v3.2",
year = 2020,
title = "EUCAST Expert Rules / EUCAST Intrinsic Resistance and Unusual Phenotypes"))
title = "'EUCAST Expert Rules' and 'EUCAST Intrinsic Resistance and Unusual Phenotypes'",
url = "https://www.eucast.org/expert_rules_and_intrinsic_resistance/"))
#' Apply EUCAST rules
format_eucast_version_nr <- function(version, markdown = TRUE) {
# for documentation - adds title, version number, year and url in markdown language
lst <- c(EUCAST_VERSION_BREAKPOINTS, EUCAST_VERSION_EXPERT_RULES)
version <- format(unique(version), nsmall = 1)
txt <- character(0)
for (i in seq_len(length(version))) {
v <- version[i]
if (markdown == TRUE) {
txt <- c(txt, paste0("[", lst[[v]]$title, " ", lst[[v]]$version_txt, "](", lst[[v]]$url, ")",
" (", lst[[v]]$year, ")"))
} else {
txt <- c(txt, paste0(lst[[version]]$title, " ", lst[[v]]$version_txt,
" (", lst[[v]]$year, ")"))
}
}
vector_and(txt, quotes = FALSE)
}
#' Apply EUCAST Rules
#'
#' @description
#' Apply rules for clinical breakpoints and intrinsic resistance as defined by the European Committee on Antimicrobial Susceptibility Testing (EUCAST, <https://eucast.org>), see *Source*.
#' Apply rules for clinical breakpoints and intrinsic resistance as defined by the European Committee on Antimicrobial Susceptibility Testing (EUCAST, <https://eucast.org>), see *Source*. Use [eucast_dosage()] to get a [data.frame] with advised dosages of a certain bug-drug combination, which is based on the [dosage] data set.
#'
#' To improve the interpretation of the antibiogram before EUCAST rules are applied, some non-EUCAST rules can applied at default, see Details.
#' @inheritSection lifecycle Stable lifecycle
#' To improve the interpretation of the antibiogram before EUCAST rules are applied, some non-EUCAST rules can applied at default, see *Details*.
#' @inheritSection lifecycle Stable Lifecycle
#' @param x data with antibiotic columns, such as `amox`, `AMX` and `AMC`
#' @param info a logical to indicate whether progress should be printed to the console, defaults to only print while in interactive sessions
#' @param rules a character vector that specifies which rules should be applied. Must be one or more of `"breakpoints"`, `"expert"`, `"other"`, `"all"`, and defaults to `c("breakpoints", "expert")`. The default value can be set to another value, e.g. using `options(AMR_eucastrules = "all")`.
#' @param verbose a [logical] to turn Verbose mode on and off (default is off). In Verbose mode, the function does not apply rules to the data, but instead returns a data set in logbook form with extensive info about which rows and columns would be effected and in which way. Using Verbose mode takes a lot more time.
#' @param version_breakpoints the version number to use for the EUCAST Clinical Breakpoints guideline. Currently supported: `r paste0(names(EUCAST_VERSION_BREAKPOINTS), collapse = ", ")`.
#' @param version_expertrules the version number to use for the EUCAST Expert Rules and Intrinsic Resistance guideline. Currently supported: `r paste0(names(EUCAST_VERSION_EXPERT_RULES), collapse = ", ")`.
#' @param ... column name of an antibiotic, please see section *Antibiotics* below
#' @param version_breakpoints the version number to use for the EUCAST Clinical Breakpoints guideline. Can be either `r vector_or(names(EUCAST_VERSION_BREAKPOINTS), reverse = TRUE)`.
#' @param version_expertrules the version number to use for the EUCAST Expert Rules and Intrinsic Resistance guideline. Can be either `r vector_or(names(EUCAST_VERSION_EXPERT_RULES), reverse = TRUE)`.
#' @param ampc_cephalosporin_resistance a character value that should be applied for AmpC de-repressed cephalosporin-resistant mutants, defaults to `NA`. Currently only works when `version_expertrules` is `3.2`; '*EUCAST Expert Rules v3.2 on Enterobacterales*' states that results of cefotaxime, ceftriaxone and ceftazidime should be reported with a note, or results should be suppressed (emptied) for these agents. A value of `NA` for this argument will remove results for these agents, while e.g. a value of `"R"` will make the results for these agents resistant. Use `NULL` to not alter the results for AmpC de-repressed cephalosporin-resistant mutants. \cr For *EUCAST Expert Rules* v3.2, this rule applies to: `r vector_and(gsub("[^a-zA-Z ]+", "", unlist(strsplit(eucast_rules_file[which(eucast_rules_file$reference.version == 3.2 & eucast_rules_file$reference.rule %like% "ampc"), "this_value"][1], "|", fixed = TRUE))), quotes = "*")`.
#' @param ... column name of an antibiotic, see section *Antibiotics* below
#' @param ab any (vector of) text that can be coerced to a valid antibiotic code with [as.ab()]
#' @param administration route of administration, either `r vector_or(dosage$administration)`
#' @param only_rsi_columns a logical to indicate whether only antibiotic columns must be detected that were [transformed to class `<rsi>`]([rsi]) on beforehand (defaults to `FALSE`)
#' @inheritParams first_isolate
#' @details
#' **Note:** This function does not translate MIC values to RSI values. Use [as.rsi()] for that. \cr
@@ -56,7 +86,7 @@ EUCAST_VERSION_EXPERT_RULES <- list("3.1" = list(version_txt = "v3.1",
#'
#' The file containing all EUCAST rules is located here: <https://github.com/msberends/AMR/blob/master/data-raw/eucast_rules.tsv>.
#'
#' ## 'Other' rules
#' ## 'Other' Rules
#'
#' Before further processing, two non-EUCAST rules about drug combinations can be applied to improve the efficacy of the EUCAST rules, and the reliability of your data (analysis). These rules are:
#'
@@ -65,26 +95,27 @@ EUCAST_VERSION_EXPERT_RULES <- list("3.1" = list(version_txt = "v3.1",
#'
#' Important examples include amoxicillin and amoxicillin/clavulanic acid, and trimethoprim and trimethoprim/sulfamethoxazole. Needless to say, for these rules to work, both drugs must be available in the data set.
#'
#' Since these rules are not officially approved by EUCAST, they are not applied at default. To use these rules, include `"other"` to the `rules` parameter, or use `eucast_rules(..., rules = "all")`.
#' Since these rules are not officially approved by EUCAST, they are not applied at default. To use these rules, include `"other"` to the `rules` argument, or use `eucast_rules(..., rules = "all")`. You can also set the option `AMR_eucastrules`, i.e. run `options(AMR_eucastrules = "all")`.
#' @section Antibiotics:
#' To define antibiotics column names, leave as it is to determine it automatically with [guess_ab_col()] or input a text (case-insensitive), or use `NULL` to skip a column (e.g. `TIC = NULL` to skip ticarcillin). Manually defined but non-existing columns will be skipped with a warning.
#'
#' The following antibiotics are used for the functions [eucast_rules()] and [mdro()]. These are shown below in the format 'name (`antimicrobial ID`, [ATC code](https://www.whocc.no/atc/structure_and_principles/))', sorted alphabetically:
#'
#' `r create_ab_documentation(c("AMC", "AMK", "AMP", "AMX", "ATM", "AVO", "AZL", "AZM", "BAM", "BPR", "CAC", "CAP", "CAT", "CAZ", "CCV", "CDR", "CDZ", "CEC", "CED", "CEI", "CEP", "CFM", "CFM1", "CFP", "CFR", "CFS", "CHL", "CID", "CIP", "CLI", "CLR", "CMX", "CMZ", "CND", "COL", "CPD", "CPM", "CPO", "CPR", "CPT", "CRB", "CRD", "CRN", "CRO", "CSL", "CTB", "CTF", "CTL", "CTT", "CTX", "CTZ", "CXM", "CYC", "CZD", "CZO", "CZX", "DAL", "DAP", "DIR", "DIT", "DIZ", "DKB", "DOR", "DOX", "ENX", "EPC", "ERV", "ERY", "ETH", "ETP", "FDX", "FEP", "FLC", "FLE", "FLR1", "FOS", "FOX", "FOX1", "FUS", "GAT", "GEH", "GEM", "GEN", "GRX", "HAP", "HET", "INH", "IPM", "ISE", "JOS", "KAN", "LEX", "LIN", "LNZ", "LOM", "LOR", "LTM", "LVX", "MAN", "MCM", "MEC", "MEM", "MEV", "MEZ", "MFX", "MID", "MNO", "MTM", "MTR", "NAL", "NEO", "NET", "NIT", "NOR", "NOV", "NVA", "OFX", "OLE", "OMC", "ORI", "OXA", "PAZ", "PEF", "PEN", "PHN", "PIP", "PLB", "PME", "PRI", "PRL", "PRU", "PVM", "PZA", "QDA", "RAM", "RFL", "RFP", "RIB", "RID", "RIF", "ROK", "RST", "RXT", "SAM", "SBC", "SDI", "SDM", "SIS", "SLF", "SLF1", "SLF10", "SLF11", "SLF12", "SLF13", "SLF2", "SLF3", "SLF4", "SLF5", "SLF6", "SLF7", "SLF8", "SLF9", "SLT1", "SLT2", "SLT3", "SLT4", "SLT5", "SMX", "SPI", "SPT", "SPX", "STH", "STR", "STR1", "SUD", "SUT", "SXT", "SZO", "TAL", "TCC", "TCM", "TCY", "TEC", "TEM", "TGC", "THA", "TIC", "TLT", "TLV", "TMP", "TMX", "TOB", "TRL", "TVA", "TZD", "TZP", "VAN"))`
#' `r create_ab_documentation(c("AMC", "AMK", "AMP", "AMX", "ATM", "AVO", "AZL", "AZM", "BAM", "BPR", "CAC", "CAT", "CAZ", "CCP", "CCV", "CCX", "CDC", "CDR", "CDZ", "CEC", "CED", "CEI", "CEM", "CEP", "CFM", "CFM1", "CFP", "CFR", "CFS", "CFZ", "CHE", "CHL", "CID", "CIP", "CLI", "CLR", "CMX", "CMZ", "CND", "COL", "CPD", "CPI", "CPL", "CPM", "CPO", "CPR", "CPT", "CPX", "CRB", "CRD", "CRN", "CRO", "CSL", "CTB", "CTC", "CTF", "CTL", "CTS", "CTT", "CTX", "CTZ", "CXM", "CYC", "CZA", "CZD", "CZO", "CZP", "CZX", "DAL", "DAP", "DIR", "DIT", "DIX", "DIZ", "DKB", "DOR", "DOX", "ENX", "EPC", "ERY", "ETP", "FEP", "FLC", "FLE", "FLR1", "FOS", "FOV", "FOX", "FOX1", "FUS", "GAT", "GEM", "GEN", "GRX", "HAP", "HET", "IPM", "ISE", "JOS", "KAN", "LEX", "LIN", "LNZ", "LOM", "LOR", "LTM", "LVX", "MAN", "MCM", "MEC", "MEM", "MEV", "MEZ", "MFX", "MID", "MNO", "MTM", "NAL", "NEO", "NET", "NIT", "NOR", "NOV", "NVA", "OFX", "OLE", "ORI", "OXA", "PAZ", "PEF", "PEN", "PHN", "PIP", "PLB", "PME", "PRI", "PRL", "PRU", "PVM", "QDA", "RAM", "RFL", "RID", "RIF", "ROK", "RST", "RXT", "SAM", "SBC", "SDI", "SDM", "SIS", "SLF", "SLF1", "SLF10", "SLF11", "SLF12", "SLF13", "SLF2", "SLF3", "SLF4", "SLF5", "SLF6", "SLF7", "SLF8", "SLF9", "SLT1", "SLT2", "SLT3", "SLT4", "SLT5", "SMX", "SPI", "SPX", "STR", "STR1", "SUD", "SUT", "SXT", "SZO", "TAL", "TCC", "TCM", "TCY", "TEC", "TEM", "TGC", "THA", "TIC", "TIO", "TLT", "TLV", "TMP", "TMX", "TOB", "TRL", "TVA", "TZD", "TZP", "VAN"))`
#' @aliases EUCAST
#' @rdname eucast_rules
#' @export
#' @return The input of `x`, possibly with edited values of antibiotics. Or, if `verbose = TRUE`, a [data.frame] with all original and new values of the affected bug-drug combinations.
#' @source
#' - EUCAST Expert Rules. Version 2.0, 2012.\cr
#' Leclercq et al. **EUCAST expert rules in antimicrobial susceptibility testing.** *Clin Microbiol Infect.* 2013;19(2):141-60. [(link)](https://doi.org/10.1111/j.1469-0691.2011.03703.x)
#' Leclercq et al. **EUCAST expert rules in antimicrobial susceptibility testing.** *Clin Microbiol Infect.* 2013;19(2):141-60; \doi{https://doi.org/10.1111/j.1469-0691.2011.03703.x}
#' - EUCAST Expert Rules, Intrinsic Resistance and Exceptional Phenotypes Tables. Version 3.1, 2016. [(link)](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/Expert_rules_intrinsic_exceptional_V3.1.pdf)
#' - EUCAST Intrinsic Resistance and Unusual Phenotypes. Version 3.2, 2020. [(link)](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/2020/Intrinsic_Resistance_and_Unusual_Phenotypes_Tables_v3.2_20200225.pdf)
#' - EUCAST Breakpoint tables for interpretation of MICs and zone diameters. Version 9.0, 2019. [(link)](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Breakpoint_tables/v_9.0_Breakpoint_Tables.xlsx)
#' - EUCAST Breakpoint tables for interpretation of MICs and zone diameters. Version 10.0, 2020. [(link)](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Breakpoint_tables/v_10.0_Breakpoint_Tables.xlsx)
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' - EUCAST Breakpoint tables for interpretation of MICs and zone diameters. Version 11.0, 2021. [(link)](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Breakpoint_tables/v_11.0_Breakpoint_Tables.xlsx)
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' \donttest{
#' a <- data.frame(mo = c("Staphylococcus aureus",
@@ -126,14 +157,27 @@ EUCAST_VERSION_EXPERT_RULES <- list("3.1" = list(version_txt = "v3.1",
#' # containing all details about the transformations:
#' c <- eucast_rules(a, verbose = TRUE)
#' }
#'
#' eucast_dosage(c("tobra", "genta", "cipro"), "iv")
eucast_rules <- function(x,
col_mo = NULL,
info = interactive(),
rules = getOption("AMR_eucastrules", default = c("breakpoints", "expert")),
verbose = FALSE,
version_breakpoints = 10.0,
version_breakpoints = 11.0,
version_expertrules = 3.2,
ampc_cephalosporin_resistance = NA,
only_rsi_columns = FALSE,
...) {
meet_criteria(x, allow_class = "data.frame")
meet_criteria(col_mo, allow_class = "character", has_length = 1, is_in = colnames(x), allow_NULL = TRUE)
meet_criteria(info, allow_class = "logical", has_length = 1)
meet_criteria(rules, allow_class = "character", has_length = c(1, 2, 3, 4), is_in = c("breakpoints", "expert", "other", "all"))
meet_criteria(verbose, allow_class = "logical", has_length = 1)
meet_criteria(version_breakpoints, allow_class = c("numeric", "integer"), has_length = 1, is_in = as.double(names(EUCAST_VERSION_BREAKPOINTS)))
meet_criteria(version_expertrules, allow_class = c("numeric", "integer"), has_length = 1, is_in = as.double(names(EUCAST_VERSION_EXPERT_RULES)))
meet_criteria(ampc_cephalosporin_resistance, has_length = 1, allow_NA = TRUE, allow_NULL = TRUE, is_in = c("R", "S", "I"))
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
x_deparsed <- deparse(substitute(x))
if (length(x_deparsed) > 1 || !all(x_deparsed %like% "[a-z]+")) {
@@ -142,12 +186,6 @@ eucast_rules <- function(x,
check_dataset_integrity()
version_breakpoints <- as.double(gsub("[^0-9.]+", "", version_breakpoints))
version_expertrules <- as.double(gsub("[^0-9.]+", "", version_expertrules))
stop_ifnot(version_breakpoints %in% as.double(names(EUCAST_VERSION_BREAKPOINTS)),
"EUCAST version ", version_breakpoints, " for clinical breakpoints not found")
stop_ifnot(version_expertrules %in% as.double(names(EUCAST_VERSION_EXPERT_RULES)),
"EUCAST version ", version_expertrules, " for expert rules/intrinsic resistance not found")
breakpoints_info <- EUCAST_VERSION_BREAKPOINTS[[which(as.double(names(EUCAST_VERSION_BREAKPOINTS)) == version_breakpoints)]]
expertrules_info <- EUCAST_VERSION_EXPERT_RULES[[which(as.double(names(EUCAST_VERSION_EXPERT_RULES)) == version_expertrules)]]
@@ -167,23 +205,19 @@ eucast_rules <- function(x,
q_continue <- utils::menu(choices = c("OK", "Cancel"), graphics = FALSE, title = txt)
}
if (q_continue %in% c(FALSE, 2)) {
message("Cancelled, returning original data")
message_("Cancelled, returning original data", add_fn = font_red, as_note = FALSE)
return(x)
}
}
stop_ifnot(is.data.frame(x), "`x` must be a data frame")
# try to find columns based on type
# -- mo
if (is.null(col_mo)) {
col_mo <- search_type_in_df(x = x, type = "mo", info = info)
stop_if(is.null(col_mo), "`col_mo` must be set")
} else {
stop_ifnot(col_mo %in% colnames(x), "column '", col_mo, "' (`col_mo`) not found")
}
stop_if(is.null(col_mo), "`col_mo` must be set")
stop_ifnot(col_mo %in% colnames(x), "column '", col_mo, "' (`col_mo`) not found")
stop_ifnot(all(rules %in% c("breakpoints", "expert", "other", "all")),
'`rules` must be one or more of: "breakpoints", "expert", "other", "all".')
decimal.mark <- getOption("OutDec")
big.mark <- ifelse(decimal.mark != ",", ",", ".")
@@ -246,8 +280,9 @@ eucast_rules <- function(x,
hard_dependencies = NULL,
verbose = verbose,
info = info,
only_rsi_columns = only_rsi_columns,
...)
AMC <- cols_ab["AMC"]
AMK <- cols_ab["AMK"]
AMP <- cols_ab["AMP"]
@@ -261,53 +296,66 @@ eucast_rules <- function(x,
CAC <- cols_ab["CAC"]
CAT <- cols_ab["CAT"]
CAZ <- cols_ab["CAZ"]
CCP <- cols_ab["CCP"]
CCV <- cols_ab["CCV"]
CCX <- cols_ab["CCX"]
CDC <- cols_ab["CDC"]
CDR <- cols_ab["CDR"]
CDZ <- cols_ab["CDZ"]
CEC <- cols_ab["CEC"]
CED <- cols_ab["CED"]
CEI <- cols_ab["CEI"]
CEM <- cols_ab["CEM"]
CEP <- cols_ab["CEP"]
CFM <- cols_ab["CFM"]
CFM1 <- cols_ab["CFM1"]
CFP <- cols_ab["CFP"]
CFR <- cols_ab["CFR"]
CFS <- cols_ab["CFS"]
CFZ <- cols_ab["CFZ"]
CHE <- cols_ab["CHE"]
CHL <- cols_ab["CHL"]
CID <- cols_ab["CID"]
CIP <- cols_ab["CIP"]
CLI <- cols_ab["CLI"]
CLI <- cols_ab["CLI"]
CLR <- cols_ab["CLR"]
CMX <- cols_ab["CMX"]
CMZ <- cols_ab["CMZ"]
CND <- cols_ab["CND"]
COL <- cols_ab["COL"]
CPD <- cols_ab["CPD"]
CPI <- cols_ab["CPI"]
CPL <- cols_ab["CPL"]
CPM <- cols_ab["CPM"]
CPO <- cols_ab["CPO"]
CPR <- cols_ab["CPR"]
CPT <- cols_ab["CPT"]
CPX <- cols_ab["CPX"]
CRB <- cols_ab["CRB"]
CRD <- cols_ab["CRD"]
CRN <- cols_ab["CRN"]
CRO <- cols_ab["CRO"]
CSL <- cols_ab["CSL"]
CTB <- cols_ab["CTB"]
CTC <- cols_ab["CTC"]
CTF <- cols_ab["CTF"]
CTL <- cols_ab["CTL"]
CTS <- cols_ab["CTS"]
CTT <- cols_ab["CTT"]
CTX <- cols_ab["CTX"]
CTZ <- cols_ab["CTZ"]
CXM <- cols_ab["CXM"]
CYC <- cols_ab["CYC"]
CZA <- cols_ab["CZA"]
CZD <- cols_ab["CZD"]
CZO <- cols_ab["CZO"]
CZP <- cols_ab["CZP"]
CZX <- cols_ab["CZX"]
DAL <- cols_ab["DAL"]
DAP <- cols_ab["DAP"]
DIR <- cols_ab["DIR"]
DIT <- cols_ab["DIT"]
DIX <- cols_ab["DIX"]
DIZ <- cols_ab["DIZ"]
DKB <- cols_ab["DKB"]
DOR <- cols_ab["DOR"]
@@ -321,6 +369,7 @@ eucast_rules <- function(x,
FLE <- cols_ab["FLE"]
FLR1 <- cols_ab["FLR1"]
FOS <- cols_ab["FOS"]
FOV <- cols_ab["FOV"]
FOX <- cols_ab["FOX"]
FOX1 <- cols_ab["FOX1"]
FUS <- cols_ab["FUS"]
@@ -374,7 +423,6 @@ eucast_rules <- function(x,
PRU <- cols_ab["PRU"]
PVM <- cols_ab["PVM"]
QDA <- cols_ab["QDA"]
QDA <- cols_ab["QDA"]
RAM <- cols_ab["RAM"]
RFL <- cols_ab["RFL"]
RID <- cols_ab["RID"]
@@ -424,6 +472,7 @@ eucast_rules <- function(x,
TGC <- cols_ab["TGC"]
THA <- cols_ab["THA"]
TIC <- cols_ab["TIC"]
TIO <- cols_ab["TIO"]
TLT <- cols_ab["TLT"]
TLV <- cols_ab["TLV"]
TMP <- cols_ab["TMP"]
@@ -442,14 +491,14 @@ eucast_rules <- function(x,
if (ab_missing(AMP) & !ab_missing(AMX)) {
# ampicillin column is missing, but amoxicillin is available
if (info == TRUE) {
message(font_blue(paste0("NOTE: Using column `", font_bold(AMX), "` as input for ampicillin since many EUCAST rules depend on it.")))
message_("Using column '", font_bold(AMX), "' as input for ampicillin since many EUCAST rules depend on it.")
}
AMP <- AMX
}
# data preparation ----
if (info == TRUE & NROW(x) > 10000) {
message(font_blue("NOTE: Preparing data..."), appendLF = FALSE)
message_("Preparing data...", appendLF = FALSE, as_note = FALSE)
}
# nolint start
@@ -457,9 +506,10 @@ eucast_rules <- function(x,
aminoglycosides <- c(AMK, DKB, GEN, ISE, KAN, NEO, NET, RST, SIS, STR, STR1, TOB)
aminopenicillins <- c(AMP, AMX)
carbapenems <- c(DOR, ETP, IPM, MEM, MEV)
cephalosporins <- c(CDZ, CAC, CEC, CFR, RID, MAN, CTZ, CZD, CZO, CDR, DIT, FEP, CAT, CFM, CMX, CMZ, DIZ, CID, CFP, CSL, CND, CTX, CTT, CTF, FOX, CPM, CPO, CPD, CPR, CRD, CFS, CPT, CAZ, CCV, CTL, CTB, CZX, BPR, CFM1, CEI, CRO, CXM, LEX, CEP, HAP, CED, LTM, LOR)
cephalosporins <- c(CDZ, CCP, CAC, CEC, CFR, RID, MAN, CTZ, CZD, CZO, CDR, DIT, FEP, CAT, CFM, CMX, CMZ, DIZ, CID, CFP, CSL, CND, CTX, CTT, CTF, FOX, CPM, CPO, CPD, CPR, CRD, CFS, CPT, CAZ, CCV, CTL, CTB, CZX, BPR, CFM1, CEI, CRO, CXM, LEX, CEP, HAP, CED, LTM, LOR)
cephalosporins_1st <- c(CAC, CFR, RID, CTZ, CZD, CZO, CRD, CTL, LEX, CEP, HAP, CED)
cephalosporins_2nd <- c(CEC, MAN, CMZ, CID, CND, CTT, CTF, FOX, CPR, CXM, LOR)
cephalosporins_3rd <- c(CDZ, CCP, CCX, CDR, DIT, DIX, CAT, CPI, CFM, CMX, DIZ, CFP, CSL, CTX, CTC, CTS, CHE, FOV, CFZ, CPM, CPD, CPX, CDC, CFS, CAZ, CZA, CCV, CEM, CPL, CTB, TIO, CZX, CZP, CRO, LTM)
cephalosporins_except_CAZ <- cephalosporins[cephalosporins != ifelse(is.null(CAZ), "", CAZ)]
fluoroquinolones <- c(CIP, ENX, FLE, GAT, GEM, GRX, LVX, LOM, MFX, NOR, OFX, PAZ, PEF, PRU, RFL, SPX, TMX, TVA)
glycopeptides <- c(AVO, NVA, RAM, TEC, TCM, VAN) # dalba/orita/tela are in lipoglycopeptides
@@ -502,7 +552,7 @@ eucast_rules <- function(x,
strsplit(",") %pm>%
unlist() %pm>%
trimws() %pm>%
sapply(function(x) if (x %in% antibiotics$ab) ab_name(x, language = NULL, tolower = TRUE) else x) %pm>%
vapply(FUN.VALUE = character(1), function(x) if (x %in% antibiotics$ab) ab_name(x, language = NULL, tolower = TRUE) else x) %pm>%
sort() %pm>%
paste(collapse = ", ")
x <- gsub("_", " ", x, fixed = TRUE)
@@ -522,7 +572,9 @@ eucast_rules <- function(x,
x <- paste(paste0(ab_names, collapse = " and "), "are both")
} else {
# like PEN,FOX,GEN S (although dependency on > 2 ABx does not exist at the moment)
x <- paste(paste0(ab_names, collapse = " and "), "are all")
# nolint start
# x <- paste(paste0(ab_names, collapse = " and "), "are all")
# nolint end
}
return(paste0(x, " '", ab_results, "'"))
} else {
@@ -563,11 +615,14 @@ eucast_rules <- function(x,
x <- as.data.frame(x, stringsAsFactors = FALSE) # no tibbles, data.tables, etc.
rownames(x) <- NULL # will later be restored with old_attributes
# create unique row IDs - combination of the MO and all ABx columns (so they will only run once per unique combination)
x$`.rowid` <- sapply(as.list(as.data.frame(t(x[, c(col_mo, cols_ab), drop = FALSE]))), function(x) {
x[is.na(x)] <- "."
paste0(x, collapse = "")
})
x$`.rowid` <- vapply(FUN.VALUE = character(1),
as.list(as.data.frame(t(x[, c(col_mo, cols_ab), drop = FALSE]),
stringsAsFactors = FALSE)),
function(x) {
x[is.na(x)] <- "."
paste0(x, collapse = "")
})
# save original table, with the new .rowid column
x.bak <- x
# keep only unique rows for MO and ABx
@@ -576,13 +631,13 @@ eucast_rules <- function(x,
# big speed gain! only analyse unique rows:
pm_distinct(`.rowid`, .keep_all = TRUE) %pm>%
as.data.frame(stringsAsFactors = FALSE)
x[, col_mo] <- as.mo(x[, col_mo, drop = TRUE])
x[, col_mo] <- as.mo(as.character(x[, col_mo, drop = TRUE]))
x <- x %pm>%
left_join_microorganisms(by = col_mo, suffix = c("_oldcols", ""))
x$gramstain <- mo_gramstain(x[, col_mo, drop = TRUE], language = NULL)
x$genus_species <- paste(x$genus, x$species)
if (info == TRUE & NROW(x) > 10000) {
message(font_blue("OK."))
message_(" OK.", add_fn = list(font_green, font_bold), as_note = FALSE)
}
if (any(x$genus == "Staphylococcus", na.rm = TRUE)) {
@@ -600,9 +655,11 @@ eucast_rules <- function(x,
# Other rules: enzyme inhibitors ------------------------------------------
if (any(c("all", "other") %in% rules)) {
if (info == TRUE) {
cat(font_bold(paste0("\nRules by this AMR package (",
font_red(paste0("v", utils::packageVersion("AMR"), ", ",
format(utils::packageDate("AMR"), "%Y"))), "), see ?eucast_rules\n")))
cat("\n")
cat(word_wrap(
font_bold(paste0("Rules by this AMR package (",
font_red(paste0("v", utils::packageDescription("AMR")$Version, ", ",
format(as.Date(utils::packageDescription("AMR")$Date), format = "%Y"))), "), see ?eucast_rules\n"))))
}
ab_enzyme <- subset(antibiotics, name %like% "/")[, c("ab", "name")]
@@ -613,14 +670,18 @@ eucast_rules <- function(x,
ab_name_base <- ab_name(cols_ab[ab_enzyme[i, ]$base_ab], language = NULL, tolower = TRUE)
ab_name_enzyme <- ab_name(cols_ab[ab_enzyme[i, ]$ab], language = NULL, tolower = TRUE)
# Set base to R where base + enzyme inhibitor is R
# Set base to R where base + enzyme inhibitor is R ----
rule_current <- paste0("Set ", ab_name_base, " (", cols_ab[ab_enzyme[i, ]$base_ab], ") = R where ",
ab_name_enzyme, " (", cols_ab[ab_enzyme[i, ]$ab], ") = R")
cat(rule_current)
if (info == TRUE) {
cat(word_wrap(rule_current))
cat("\n")
}
run_changes <- edit_rsi(x = x,
col_mo = col_mo,
to = "R",
rule = c(rule_current, "Other rules", "", paste0("Non-EUCAST: AMR package v", utils::packageVersion("AMR"))),
rule = c(rule_current, "Other rules", "",
paste0("Non-EUCAST: AMR package v", utils::packageDescription("AMR")$Version)),
rows = which(as.rsi_no_warning(x[, cols_ab[ab_enzyme[i, ]$ab]]) == "R"),
cols = cols_ab[ab_enzyme[i, ]$base_ab],
last_verbose_info = verbose_info,
@@ -641,16 +702,18 @@ eucast_rules <- function(x,
n_changed <- 0
}
# Set base + enzyme inhibitor to S where base is S
# Set base + enzyme inhibitor to S where base is S ----
rule_current <- paste0("Set ", ab_name_enzyme, " (", cols_ab[ab_enzyme[i, ]$ab], ") = S where ",
ab_name_base, " (", cols_ab[ab_enzyme[i, ]$base_ab], ") = S")
if (info == TRUE) {
cat(rule_current)
cat(word_wrap(rule_current))
cat("\n")
}
run_changes <- edit_rsi(x = x,
col_mo = col_mo,
to = "S",
rule = c(rule_current, "Other rules", "", paste0("Non-EUCAST: AMR package v", utils::packageVersion("AMR"))),
rule = c(rule_current, "Other rules", "",
paste0("Non-EUCAST: AMR package v", utils::packageDescription("AMR")$Version)),
rows = which(as.rsi_no_warning(x[, cols_ab[ab_enzyme[i, ]$base_ab]]) == "S"),
cols = cols_ab[ab_enzyme[i, ]$ab],
last_verbose_info = verbose_info,
@@ -675,17 +738,18 @@ eucast_rules <- function(x,
} else {
if (info == TRUE) {
cat(font_red("\nSkipping inheritance rules defined by this package, such as setting trimethoprim (TMP) = R where trimethoprim/sulfamethoxazole (SXT) = R.\nUse eucast_rules(..., rules = \"all\") to also apply those rules.\n"))
cat("\n")
message_("Skipping inheritance rules defined by this package, such as setting trimethoprim (TMP) = R where trimethoprim/sulfamethoxazole (SXT) = R. Use `eucast_rules(..., rules = \"all\")` to also apply those rules.")
}
}
# Official EUCAST rules ---------------------------------------------------
eucast_notification_shown <- FALSE
if (!is.null(list(...)$eucast_rules_df)) {
# this allows: eucast_rules(x, eucast_rules_df = AMR:::eucast_rules_file %pm>% filter(is.na(have_these_values)))
# this allows: eucast_rules(x, eucast_rules_df = AMR:::eucast_rules_file %>% filter(is.na(have_these_values)))
eucast_rules_df <- list(...)$eucast_rules_df
} else {
# otherwise internal data file, created in data-raw/internals.R
# otherwise internal data file, created in data-raw/_internals.R
eucast_rules_df <- eucast_rules_file
}
@@ -700,6 +764,13 @@ eucast_rules <- function(x,
!reference.rule_group %like% "expert" |
(reference.rule_group %like% "expert" & reference.version == version_expertrules))
}
# filter out AmpC de-repressed cephalosporin-resistant mutants ----
if (is.null(ampc_cephalosporin_resistance)) {
eucast_rules_df <- subset(eucast_rules_df,
!reference.rule %like% "ampc")
} else {
eucast_rules_df[which(eucast_rules_df$reference.rule %like% "ampc"), "to_value"] <- as.character(ampc_cephalosporin_resistance)
}
for (i in seq_len(nrow(eucast_rules_df))) {
@@ -739,9 +810,10 @@ eucast_rules <- function(x,
if (info == TRUE) {
# Print EUCAST intro ------------------------------------------------------
if (!rule_group_current %like% "other" & eucast_notification_shown == FALSE) {
cat(paste0("\n", font_grey(strrep("-", 0.95 * options()$width)),
"\nRules by the ", font_bold("European Committee on Antimicrobial Susceptibility Testing (EUCAST)"),
"\n", font_blue("https://eucast.org/"), "\n"))
cat(
paste0("\n", font_grey(strrep("-", 0.95 * options()$width)), "\n",
word_wrap("Rules by the ", font_bold("European Committee on Antimicrobial Susceptibility Testing (EUCAST)")), "\n",
font_blue("https://eucast.org/"), "\n"))
eucast_notification_shown <- TRUE
}
@@ -751,18 +823,24 @@ eucast_rules <- function(x,
cat(font_bold(
ifelse(
rule_group_current %like% "breakpoint",
paste0("\n", breakpoints_info$title, " (",
font_red(paste0(breakpoints_info$version_txt, ", ", breakpoints_info$year)), ")\n"),
paste0("\n",
word_wrap(
breakpoints_info$title, " (",
font_red(paste0(breakpoints_info$version_txt, ", ", breakpoints_info$year)), ")\n")),
ifelse(
rule_group_current %like% "expert",
paste0("\n", expertrules_info$title, " (",
font_red(paste0(expertrules_info$version_txt, ", ", expertrules_info$year)), ")\n"),
""))))
paste0("\n",
word_wrap(
expertrules_info$title, " (",
font_red(paste0(expertrules_info$version_txt, ", ", expertrules_info$year)), ")\n")),
""))), "\n")
}
# Print rule -------------------------------------------------------------
if (rule_current != rule_previous) {
# is new rule within group, print its name
cat(markup_italics_where_needed(rule_current))
cat(markup_italics_where_needed(word_wrap(rule_current,
width = getOption("width") - 30,
extra_indent = 6)))
warned <- FALSE
}
}
@@ -772,7 +850,7 @@ eucast_rules <- function(x,
like_is_one_of <- trimws(eucast_rules_df[i, "like.is.one_of", drop = TRUE])
mo_value <- trimws(eucast_rules_df[i, "this_value", drop = TRUE])
# be sure to comprise all coagulase-negative/-positive Staphylococci when they are mentioned
# be sure to comprise all coagulase-negative/-positive staphylococci when they are mentioned
if (mo_value %like% "coagulase" && any(x$genus == "Staphylococcus", na.rm = TRUE)) {
if (mo_value %like% "negative") {
eucast_rules_df[i, "this_value"] <- paste0("^(", paste0(all_staph[which(all_staph$CNS_CPS %like% "negative"),
@@ -818,7 +896,7 @@ eucast_rules <- function(x,
target_value <- eucast_rules_df[i, "to_value", drop = TRUE]
if (is.na(source_antibiotics)) {
rows <- tryCatch(which(x[, if_mo_property, drop = TRUE] %like_perl% mo_value),
rows <- tryCatch(which(x[, if_mo_property, drop = TRUE] %like% mo_value),
error = function(e) integer(0))
} else {
source_antibiotics <- get_antibiotic_columns(source_antibiotics, x)
@@ -828,22 +906,24 @@ eucast_rules <- function(x,
if (length(source_antibiotics) == 0) {
rows <- integer(0)
} else if (length(source_antibiotics) == 1) {
rows <- tryCatch(which(x[, if_mo_property, drop = TRUE] %like_perl% mo_value
rows <- tryCatch(which(x[, if_mo_property, drop = TRUE] %like% mo_value
& as.rsi_no_warning(x[, source_antibiotics[1L]]) == source_value[1L]),
error = function(e) integer(0))
} else if (length(source_antibiotics) == 2) {
rows <- tryCatch(which(x[, if_mo_property, drop = TRUE] %like_perl% mo_value
rows <- tryCatch(which(x[, if_mo_property, drop = TRUE] %like% mo_value
& as.rsi_no_warning(x[, source_antibiotics[1L]]) == source_value[1L]
& as.rsi_no_warning(x[, source_antibiotics[2L]]) == source_value[2L]),
error = function(e) integer(0))
} else if (length(source_antibiotics) == 3) {
rows <- tryCatch(which(x[, if_mo_property, drop = TRUE] %like_perl% mo_value
& as.rsi_no_warning(x[, source_antibiotics[1L]]) == source_value[1L]
& as.rsi_no_warning(x[, source_antibiotics[2L]]) == source_value[2L]
& as.rsi_no_warning(x[, source_antibiotics[3L]]) == source_value[3L]),
error = function(e) integer(0))
# nolint start
# } else if (length(source_antibiotics) == 3) {
# rows <- tryCatch(which(x[, if_mo_property, drop = TRUE] %like% mo_value
# & as.rsi_no_warning(x[, source_antibiotics[1L]]) == source_value[1L]
# & as.rsi_no_warning(x[, source_antibiotics[2L]]) == source_value[2L]
# & as.rsi_no_warning(x[, source_antibiotics[3L]]) == source_value[3L]),
# error = function(e) integer(0))
# nolint end
} else {
stop_("only 3 antibiotics supported for source_antibiotics")
stop_("only 2 antibiotics supported for source_antibiotics")
}
}
@@ -888,7 +968,7 @@ eucast_rules <- function(x,
by = c(".rowid" = "rowid")) %pm>%
pm_select(-`.rowid`) %pm>%
pm_select(row, pm_everything()) %pm>%
pm_filter(!is.na(new)) %pm>%
pm_filter(!is.na(new) | is.na(new) & !is.na(old)) %pm>%
pm_arrange(row, rule_group, rule_name, col)
rownames(verbose_info) <- NULL
}
@@ -902,12 +982,12 @@ eucast_rules <- function(x,
}
cat(paste0("\n", font_grey(strrep("-", 0.95 * options()$width)), "\n"))
cat(paste0("The rules ", paste0(wouldve, "affected "),
font_bold(formatnr(pm_n_distinct(verbose_info$row)),
"out of", formatnr(nrow(x.bak)),
"rows"),
", making a total of ",
font_bold(formatnr(nrow(verbose_info)), "edits\n")))
cat(word_wrap(paste0("The rules ", paste0(wouldve, "affected "),
font_bold(formatnr(pm_n_distinct(verbose_info$row)),
"out of", formatnr(nrow(x.bak)),
"rows"),
", making a total of ",
font_bold(formatnr(nrow(verbose_info)), "edits\n"))))
total_n_added <- verbose_info %pm>% pm_filter(is.na(old)) %pm>% nrow()
total_n_changed <- verbose_info %pm>% pm_filter(!is.na(old)) %pm>% nrow()
@@ -949,6 +1029,7 @@ eucast_rules <- function(x,
if (total_n_changed > 0) {
changed_summary <- verbose_info %pm>%
pm_filter(!is.na(old)) %pm>%
pm_mutate(new = ifelse(is.na(new), "NA", new)) %pm>%
pm_count(old, new, name = "n")
cat(paste(" -",
paste0(formatnr(changed_summary$n), " test result", ifelse(changed_summary$n > 1, "s", ""), " changed from ",
@@ -959,21 +1040,22 @@ eucast_rules <- function(x,
cat(paste0(font_grey(strrep("-", 0.95 * options()$width)), "\n"))
if (verbose == FALSE & total_n_added + total_n_changed > 0) {
cat(paste("\nUse", font_bold("eucast_rules(..., verbose = TRUE)"), "(on your original data) to get a data.frame with all specified edits instead.\n\n"))
cat("\n", word_wrap("Use ", font_bold("eucast_rules(..., verbose = TRUE)"), " (on your original data) to get a data.frame with all specified edits instead."), "\n\n", sep = "")
} else if (verbose == TRUE) {
cat(paste0("\nUsed 'Verbose mode' (", font_bold("verbose = TRUE"), "), which returns a data.frame with all specified edits.\nUse ", font_bold("verbose = FALSE"), " to apply the rules on your data.\n\n"))
cat("\n", word_wrap("Used 'Verbose mode' (", font_bold("verbose = TRUE"), "), which returns a data.frame with all specified edits.\nUse ", font_bold("verbose = FALSE"), " to apply the rules on your data."), "\n\n", sep = "")
}
}
if (length(warn_lacking_rsi_class) > 0) {
warn_lacking_rsi_class <- unique(warn_lacking_rsi_class)
warning("Not all columns with antimicrobial results are of class <rsi>. Transform them on beforehand, with e.g.:\n",
" ", x_deparsed, " %>% mutate_if(is.rsi.eligible, as.rsi)\n",
" ", x_deparsed, " %>% as.rsi(", ifelse(length(warn_lacking_rsi_class) == 1,
warn_lacking_rsi_class,
paste0(warn_lacking_rsi_class[1], ":", warn_lacking_rsi_class[length(warn_lacking_rsi_class)])),
")",
call. = FALSE)
warning_("Not all columns with antimicrobial results are of class <rsi>. Transform them on beforehand, with e.g.:\n",
" ", x_deparsed, " %>% mutate_if(is.rsi.eligible, as.rsi)\n",
" ", x_deparsed, " %>% mutate(across((is.rsi.eligible), as.rsi))\n",
" ", x_deparsed, " %>% as.rsi(", ifelse(length(warn_lacking_rsi_class) == 1,
warn_lacking_rsi_class,
paste0(warn_lacking_rsi_class[1], ":", warn_lacking_rsi_class[length(warn_lacking_rsi_class)])),
")",
call = FALSE)
}
# Return data set ---------------------------------------------------------
@@ -1024,25 +1106,25 @@ edit_rsi <- function(x,
if (length(rows) > 0 & length(cols) > 0) {
new_edits <- x
if (any(!sapply(x[, cols, drop = FALSE], is.rsi), na.rm = TRUE)) {
track_changes$rsi_warn <- cols[!sapply(x[, cols, drop = FALSE], is.rsi)]
if (any(!vapply(FUN.VALUE = logical(1), x[, cols, drop = FALSE], is.rsi), na.rm = TRUE)) {
track_changes$rsi_warn <- cols[!vapply(FUN.VALUE = logical(1), x[, cols, drop = FALSE], is.rsi)]
}
tryCatch(
# insert into original table
new_edits[rows, cols] <- to,
warning = function(w) {
if (w$message %like% "invalid factor level") {
xyz <- sapply(cols, function(col) {
new_edits[, col] <- factor(x = as.character(pm_pull(new_edits, col)), levels = c(to, levels(pm_pull(new_edits, col))))
# x[, col] <<- factor(x = as.character(pm_pull(x, col)), levels = c(to, levels(pm_pull(x, col))))
invisible()
xyz <- vapply(FUN.VALUE = logical(1), cols, function(col) {
new_edits[, col] <<- factor(x = as.character(pm_pull(new_edits, col)),
levels = unique(c(to, levels(pm_pull(new_edits, col)))))
TRUE
})
new_edits[rows, cols] <- to
warning('Value "', to, '" added to the factor levels of column(s) `', paste(cols, collapse = "`, `"), "` because this value was not an existing factor level.\nA better way is to use as.rsi() on beforehand on antimicrobial columns to guarantee the right structure.", call. = FALSE)
suppressWarnings(new_edits[rows, cols] <<- to)
warning_('Value "', to, '" added to the factor levels of column(s) `', paste(cols, collapse = "`, `"), "` because this value was not an existing factor level. A better way is to use as.rsi() on beforehand on antimicrobial columns to guarantee the right structure.", call = FALSE)
txt_warning()
warned <- FALSE
} else {
warning(w$message, call. = FALSE)
warning_(w$message, call = FALSE)
txt_warning()
cat("\n") # txt_warning() does not append a "\n" on itself
}
@@ -1076,9 +1158,11 @@ edit_rsi <- function(x,
stringsAsFactors = FALSE)
colnames(verbose_new) <- c("rowid", "col", "mo_fullname", "old", "new",
"rule", "rule_group", "rule_name", "rule_source")
verbose_new <- verbose_new %pm>% pm_filter(old != new | is.na(old))
verbose_new <- verbose_new %pm>% pm_filter(old != new | is.na(old) | is.na(new) & !is.na(old))
# save changes to data set 'verbose_info'
track_changes$verbose_info <- rbind(track_changes$verbose_info, verbose_new)
track_changes$verbose_info <- rbind(track_changes$verbose_info,
verbose_new,
stringsAsFactors = FALSE)
# count adds and changes
track_changes$added <- track_changes$added + verbose_new %pm>%
pm_filter(is.na(old)) %pm>%
@@ -1095,3 +1179,38 @@ edit_rsi <- function(x,
}
return(track_changes)
}
#' @rdname eucast_rules
#' @export
eucast_dosage <- function(ab, administration = "iv", version_breakpoints = 11.0) {
meet_criteria(ab, allow_class = c("character", "numeric", "integer", "factor"))
meet_criteria(administration, allow_class = "character", is_in = dosage$administration[!is.na(dosage$administration)], has_length = 1)
meet_criteria(version_breakpoints, allow_class = c("numeric", "integer"), has_length = 1, is_in = as.double(names(EUCAST_VERSION_BREAKPOINTS)))
# show used version_breakpoints number once per session (pkg_env will reload every session)
if (message_not_thrown_before(paste0("eucast_dosage_v", gsub("[^0-9]", "", version_breakpoints)), entire_session = TRUE)) {
message_("Dosages for antimicrobial drugs, as meant for ",
format_eucast_version_nr(version_breakpoints, markdown = FALSE), ". ",
font_red("This note will be shown once per session."))
remember_thrown_message(paste0("eucast_dosage_v", gsub("[^0-9]", "", version_breakpoints)), entire_session = TRUE)
}
ab <- as.ab(ab)
lst <- vector("list", length = length(ab))
for (i in seq_len(length(ab))) {
df <- AMR::dosage[which(AMR::dosage$ab == ab[i] & AMR::dosage$administration == administration), , drop = FALSE]
lst[[i]] <- list(ab = "",
name = "",
standard_dosage = ifelse("standard_dosage" %in% df$type,
df[which(df$type == "standard_dosage"), ]$original_txt,
NA_character_),
high_dosage = ifelse("high_dosage" %in% df$type,
df[which(df$type == "high_dosage"), ]$original_txt,
NA_character_))
}
out <- do.call("rbind", lapply(lst, as.data.frame, stringsAsFactors = FALSE))
rownames(out) <- NULL
out$ab <- ab
out$name <- ab_name(ab, language = NULL)
out
}
+102 -34
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,18 +20,19 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Filter isolates on result in antimicrobial class
#' Filter Isolates on Result in Antimicrobial Class
#'
#' Filter isolates on results in specific antimicrobial classes. This makes it easy to filter on isolates that were tested for e.g. any aminoglycoside, or to filter on carbapenem-resistant isolates without the need to specify the drugs.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a data set
#' @param ab_class an antimicrobial class, like `"carbapenems"`. The columns `group`, `atc_group1` and `atc_group2` of the [antibiotics] data set will be searched (case-insensitive) for this value.
#' @param result an antibiotic result: S, I or R (or a combination of more of them)
#' @param scope the scope to check which variables to check, can be `"any"` (default) or `"all"`
#' @param ... previously used when this package still depended on the `dplyr` package, now ignored
#' @param only_rsi_columns a logical to indicate whether only columns must be included that were [transformed to class `<rsi>`]([rsi]) on beforehand (defaults to `FALSE`)
#' @param ... arguments passed on to [filter_ab_class()]
#' @details All columns of `x` will be searched for known antibiotic names, abbreviations, brand names and codes (ATC, EARS-Net, WHO, etc.). This means that a filter function like e.g. [filter_aminoglycosides()] will include column names like 'gen', 'genta', 'J01GB03', 'tobra', 'Tobracin', etc.
#' @rdname filter_ab_class
#' @seealso [antibiotic_class_selectors()] for the `select()` equivalent.
@@ -70,26 +71,36 @@
#' filter_aminoglycosides("R", "all") %>%
#' filter_fluoroquinolones("R", "all")
#'
#' # with dplyr 1.0.0 and higher (that adds 'across()'), this is equal:
#' # with dplyr 1.0.0 and higher (that adds 'across()'), this is all equal:
#' # (though the row names on the first are more correct)
#' example_isolates %>% filter_carbapenems("R", "all")
#' example_isolates %>% filter(across(carbapenems(), ~. == "R"))
#' example_isolates %>% filter(across(carbapenems(), function(x) x == "R"))
#' }
#' }
filter_ab_class <- function(x,
ab_class,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
.call_depth <- list(...)$`.call_depth`
if (is.null(.call_depth)) {
.call_depth <- 0
}
meet_criteria(x, allow_class = "data.frame", .call_depth = .call_depth)
meet_criteria(ab_class, allow_class = "character", has_length = 1, .call_depth = .call_depth)
meet_criteria(result, allow_class = "character", has_length = c(1, 2, 3), allow_NULL = TRUE, .call_depth = .call_depth)
meet_criteria(scope, allow_class = "character", has_length = 1, is_in = c("all", "any"), .call_depth = .call_depth)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1, .call_depth = .call_depth)
check_dataset_integrity()
stop_ifnot(is.data.frame(x), "`x` must be a data frame")
# save to return later
x_class <- class(x)
x.bak <- x
x <- as.data.frame(x, stringsAsFactors = FALSE)
scope <- scope[1L]
if (is.null(result)) {
result <- c("S", "I", "R")
}
@@ -100,9 +111,9 @@ filter_ab_class <- function(x,
stop_ifnot(all(scope %in% c("any", "all")), "`scope` must be one of: 'any', 'all'")
# get all columns in data with names that resemble antibiotics
ab_in_data <- get_column_abx(x, info = FALSE)
ab_in_data <- get_column_abx(x, info = FALSE, only_rsi_columns = only_rsi_columns)
if (length(ab_in_data) == 0) {
message(font_blue("NOTE: no columns with class <rsi> found (see ?as.rsi), data left unchanged."))
message_("No columns with class <rsi> found (see ?as.rsi), data left unchanged.")
return(x.bak)
}
# get reference data
@@ -116,49 +127,50 @@ filter_ab_class <- function(x,
atc_group2 %like% ab_class)
ab_group <- find_ab_group(ab_class)
if (ab_group == "") {
message(font_blue(paste0("NOTE: unknown antimicrobial class '", ab_class.bak, "', data left unchanged.")))
message_("Unknown antimicrobial class '", ab_class.bak, "', data left unchanged.")
return(x.bak)
}
# get the columns with a group names in the chosen ab class
agents <- ab_in_data[names(ab_in_data) %in% ab_reference$ab]
if (length(agents) == 0) {
message(font_blue(paste0("NOTE: no antimicrobial agents of class ", ab_group,
" found (such as ", find_ab_names(ab_class, 2),
"), data left unchanged.")))
message_("No antimicrobial agents of class ", ab_group,
" found (such as ", find_ab_names(ab_class, 2),
")",
ifelse(only_rsi_columns == TRUE, " with class <rsi>,", ","),
" data left unchanged.")
return(x.bak)
}
if (length(result) == 1) {
operator <- " is "
} else {
operator <- " is one of "
}
if (scope == "any") {
scope_txt <- " or "
scope_fn <- any
} else {
scope_txt <- " and "
scope_fn <- all
if (length(agents) > 1) {
operator <- gsub("is", "are", operator)
}
}
if (length(agents) > 1) {
scope <- paste(scope, "of columns ")
operator <- " are"
scope <- paste("values in", scope, "of columns ")
} else {
scope <- "column "
operator <- " is"
scope <- "value in column "
}
if (length(result) > 1) {
operator <- paste(operator, "either")
}
# sort columns on official name
agents <- agents[order(ab_name(names(agents), language = NULL))]
message(font_blue(paste0("Filtering on ", ab_group, ": ", scope,
paste(paste0("`", font_bold(agents, collapse = NULL),
"` (", ab_name(names(agents), tolower = TRUE, language = NULL), ")"),
collapse = scope_txt),
operator, toString(result))))
x_transposed <- as.list(as.data.frame(t(x[, agents, drop = FALSE])))
filtered <- sapply(x_transposed, function(y) scope_fn(y %in% result, na.rm = TRUE))
message_("Filtering on ", ab_group, ": ", scope,
paste(paste0("`", font_bold(agents, collapse = NULL),
"` (", ab_name(names(agents), tolower = TRUE, language = NULL), ")"),
collapse = scope_txt),
operator, " ", vector_or(result, quotes = TRUE),
as_note = FALSE,
extra_indent = 6)
x_transposed <- as.list(as.data.frame(t(x[, agents, drop = FALSE]), stringsAsFactors = FALSE))
filtered <- vapply(FUN.VALUE = logical(1), x_transposed, function(y) scope_fn(y %in% result, na.rm = TRUE))
x <- x[which(filtered), , drop = FALSE]
class(x) <- x_class
x
@@ -169,11 +181,14 @@ filter_ab_class <- function(x,
filter_aminoglycosides <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "aminoglycoside",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -182,11 +197,14 @@ filter_aminoglycosides <- function(x,
filter_carbapenems <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "carbapenem",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -195,11 +213,14 @@ filter_carbapenems <- function(x,
filter_cephalosporins <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "cephalosporin",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -208,11 +229,14 @@ filter_cephalosporins <- function(x,
filter_1st_cephalosporins <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "cephalosporins (1st gen.)",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -221,11 +245,14 @@ filter_1st_cephalosporins <- function(x,
filter_2nd_cephalosporins <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "cephalosporins (2nd gen.)",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -234,11 +261,14 @@ filter_2nd_cephalosporins <- function(x,
filter_3rd_cephalosporins <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "cephalosporins (3rd gen.)",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -247,11 +277,14 @@ filter_3rd_cephalosporins <- function(x,
filter_4th_cephalosporins <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "cephalosporins (4th gen.)",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -260,11 +293,14 @@ filter_4th_cephalosporins <- function(x,
filter_5th_cephalosporins <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "cephalosporins (5th gen.)",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -273,11 +309,14 @@ filter_5th_cephalosporins <- function(x,
filter_fluoroquinolones <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "fluoroquinolone",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -286,11 +325,14 @@ filter_fluoroquinolones <- function(x,
filter_glycopeptides <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "glycopeptide",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -299,11 +341,30 @@ filter_glycopeptides <- function(x,
filter_macrolides <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "macrolide",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
#' @rdname filter_ab_class
#' @export
filter_oxazolidinones <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "oxazolidinone",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -312,11 +373,14 @@ filter_macrolides <- function(x,
filter_penicillins <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "penicillin",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -325,11 +389,14 @@ filter_penicillins <- function(x,
filter_tetracyclines <- function(x,
result = NULL,
scope = "any",
only_rsi_columns = FALSE,
...) {
filter_ab_class(x = x,
ab_class = "tetracycline",
result = result,
scope = scope,
only_rsi_columns = only_rsi_columns,
.call_depth = 1,
...)
}
@@ -341,6 +408,7 @@ find_ab_group <- function(ab_class) {
"fluoroquinolone",
"glycopeptide",
"macrolide",
"oxazolidinone",
"tetracycline"),
paste0(ab_class, "s"),
antibiotics %pm>%
+202 -115
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,42 +20,55 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Determine first (weighted) isolates
#' Determine First (Weighted) Isolates
#'
#' Determine first (weighted) isolates of all microorganisms of every patient per episode and (if needed) per specimen type.
#' @inheritSection lifecycle Stable lifecycle
#' @param x a [data.frame] containing isolates.
#' @param col_date column name of the result date (or date that is was received on the lab), defaults to the first column of with a date class
#' Determine first (weighted) isolates of all microorganisms of every patient per episode and (if needed) per specimen type. To determine patient episodes not necessarily based on microorganisms, use [is_new_episode()] that also supports grouping with the `dplyr` package.
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a [data.frame] containing isolates. Can be left blank for automatic determination, see *Examples*.
#' @param col_date column name of the result date (or date that is was received on the lab), defaults to the first column with a date class
#' @param col_patient_id column name of the unique IDs of the patients, defaults to the first column that starts with 'patient' or 'patid' (case insensitive)
#' @param col_mo column name of the IDs of the microorganisms (see [as.mo()]), defaults to the first column of class [`mo`]. Values will be coerced using [as.mo()].
#' @param col_testcode column name of the test codes. Use `col_testcode = NULL` to **not** exclude certain test codes (like test codes for screening). In that case `testcodes_exclude` will be ignored.
#' @param col_testcode column name of the test codes. Use `col_testcode = NULL` to **not** exclude certain test codes (such as test codes for screening). In that case `testcodes_exclude` will be ignored.
#' @param col_specimen column name of the specimen type or group
#' @param col_icu column name of the logicals (`TRUE`/`FALSE`) whether a ward or department is an Intensive Care Unit (ICU)
#' @param col_keyantibiotics column name of the key antibiotics to determine first *weighted* isolates, see [key_antibiotics()]. Defaults to the first column that starts with 'key' followed by 'ab' or 'antibiotics' (case insensitive). Use `col_keyantibiotics = FALSE` to prevent this.
#' @param episode_days episode in days after which a genus/species combination will be determined as 'first isolate' again. The default of 365 days is based on the guideline by CLSI, see Source.
#' @param col_keyantibiotics column name of the key antibiotics to determine first (weighted) isolates, see [key_antibiotics()]. Defaults to the first column that starts with 'key' followed by 'ab' or 'antibiotics' (case insensitive). Use `col_keyantibiotics = FALSE` to prevent this.
#' @param episode_days episode in days after which a genus/species combination will be determined as 'first isolate' again. The default of 365 days is based on the guideline by CLSI, see *Source*.
#' @param testcodes_exclude character vector with test codes that should be excluded (case-insensitive)
#' @param icu_exclude logical whether ICU isolates should be excluded (rows with value `TRUE` in column `col_icu`)
#' @param specimen_group value in column `col_specimen` to filter on
#' @param type type to determine weighed isolates; can be `"keyantibiotics"` or `"points"`, see Details
#' @param ignore_I logical to determine whether antibiotic interpretations with `"I"` will be ignored when `type = "keyantibiotics"`, see Details
#' @param points_threshold points until the comparison of key antibiotics will lead to inclusion of an isolate when `type = "points"`, see Details
#' @param icu_exclude logical whether ICU isolates should be excluded (rows with value `TRUE` in the column set with `col_icu`)
#' @param specimen_group value in the column set with `col_specimen` to filter on
#' @param type type to determine weighed isolates; can be `"keyantibiotics"` or `"points"`, see *Details*
#' @param ignore_I logical to determine whether antibiotic interpretations with `"I"` will be ignored when `type = "keyantibiotics"`, see *Details*
#' @param points_threshold points until the comparison of key antibiotics will lead to inclusion of an isolate when `type = "points"`, see *Details*
#' @param info print progress
#' @param include_unknown logical to determine whether 'unknown' microorganisms should be included too, i.e. microbial code `"UNKNOWN"`, which defaults to `FALSE`. For WHONET users, this means that all records with organism code `"con"` (*contamination*) will be excluded at default. Isolates with a microbial ID of `NA` will always be excluded as first isolate.
#' @param ... parameters passed on to the [first_isolate()] function
#' @details **WHY THIS IS SO IMPORTANT** \cr
#' To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode [(ref)](https:/pubmed.ncbi.nlm.nih.gov/17304462/). If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all *S. aureus* isolates would be overestimated, because you included this MRSA more than once. It would be [selection bias](https://en.wikipedia.org/wiki/Selection_bias).
#'
#' @param ... arguments passed on to [first_isolate()] when using [filter_first_isolate()], or arguments passed on to [key_antibiotics()] when using [filter_first_weighted_isolate()]
#' @details
#' These functions are context-aware. This means that then the `x` argument can be left blank, see *Examples*.
#'
#' The [first_isolate()] function is a wrapper around the [is_new_episode()] function, but more efficient for data sets containing microorganism codes or names.
#'
#' All isolates with a microbial ID of `NA` will be excluded as first isolate.
#'
#' ## Why this is so Important
#' To conduct an analysis of antimicrobial resistance, you should only include the first isolate of every patient per episode [(Hindler *et al.* 2007)](https://pubmed.ncbi.nlm.nih.gov/17304462/). If you would not do this, you could easily get an overestimate or underestimate of the resistance of an antibiotic. Imagine that a patient was admitted with an MRSA and that it was found in 5 different blood cultures the following week. The resistance percentage of oxacillin of all *S. aureus* isolates would be overestimated, because you included this MRSA more than once. It would be [selection bias](https://en.wikipedia.org/wiki/Selection_bias).
#'
#' The functions [filter_first_isolate()] and [filter_first_weighted_isolate()] are helper functions to quickly filter on first isolates. The function [filter_first_isolate()] is essentially equal to either:
#' ## `filter_*()` Shortcuts
#'
#' The functions [filter_first_isolate()] and [filter_first_weighted_isolate()] are helper functions to quickly filter on first isolates.
#'
#' The function [filter_first_isolate()] is essentially equal to either:
#'
#' ```
#' x[first_isolate(x, ...), ]
#' x %>% filter(first_isolate(x, ...))
#'
#' x %>% filter(first_isolate(...))
#' ```
#'
#' The function [filter_first_weighted_isolate()] is essentially equal to:
#'
#' ```
#' x %>%
#' mutate(keyab = key_antibiotics(.)) %>%
@@ -64,16 +77,16 @@
#' filter(only_weighted_firsts == TRUE) %>%
#' select(-only_weighted_firsts, -keyab)
#' ```
#' @section Key antibiotics:
#' There are two ways to determine whether isolates can be included as first *weighted* isolates which will give generally the same results:
#' @section Key Antibiotics:
#' There are two ways to determine whether isolates can be included as first weighted isolates which will give generally the same results:
#'
#' 1. Using `type = "keyantibiotics"` and parameter `ignore_I`
#' 1. Using `type = "keyantibiotics"` and argument `ignore_I`
#'
#' Any difference from S to R (or vice versa) will (re)select an isolate as a first weighted isolate. With `ignore_I = FALSE`, also differences from I to S|R (or vice versa) will lead to this. This is a reliable method and 30-35 times faster than method 2. Read more about this in the [key_antibiotics()] function.
#'
#' 2. Using `type = "points"` and parameter `points_threshold`
#' 2. Using `type = "points"` and argument `points_threshold`
#'
#' A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds `points_threshold`, which default to `2`, an isolate will be (re)selected as a first weighted isolate.
#' A difference from I to S|R (or vice versa) means 0.5 points, a difference from S to R (or vice versa) means 1 point. When the sum of points exceeds `points_threshold`, which defaults to `2`, an isolate will be (re)selected as a first weighted isolate.
#' @rdname first_isolate
#' @seealso [key_antibiotics()]
#' @export
@@ -81,29 +94,37 @@
#' @source Methodology of this function is strictly based on:
#'
#' **M39 Analysis and Presentation of Cumulative Antimicrobial Susceptibility Test Data, 4th Edition**, 2014, *Clinical and Laboratory Standards Institute (CLSI)*. <https://clsi.org/standards/products/microbiology/documents/m39/>.
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # `example_isolates` is a dataset available in the AMR package.
#' # `example_isolates` is a data set available in the AMR package.
#' # See ?example_isolates.
#'
#' # basic filtering on first isolates
#' example_isolates[first_isolate(example_isolates), ]
#'
#' \donttest{
#' # faster way, only works in R 3.2 and later:
#' example_isolates[first_isolate(), ]
#'
#' # get all first Gram-negatives
#' example_isolates[which(first_isolate() & mo_is_gram_negative()), ]
#'
#' if (require("dplyr")) {
#' # Filter on first isolates:
#' # filter on first isolates using dplyr:
#' example_isolates %>%
#' mutate(first_isolate = first_isolate(.)) %>%
#' filter(first_isolate == TRUE)
#' filter(first_isolate())
#'
#' # Short-hand versions:
#' # short-hand versions:
#' example_isolates %>%
#' filter_first_isolate()
#'
#' example_isolates %>%
#' filter_first_weighted_isolate()
#'
#' # grouped determination of first isolates (also prints group names):
#' example_isolates %>%
#' group_by(hospital_id) %>%
#' mutate(first = first_isolate())
#'
#' # Now let's see if first isolates matter:
#' # now let's see if first isolates matter:
#' A <- example_isolates %>%
#' group_by(hospital_id) %>%
#' summarise(count = n_rsi(GEN), # gentamicin availability
@@ -121,7 +142,7 @@
#' # when you (erroneously) would have used all isolates for analysis.
#' }
#' }
first_isolate <- function(x,
first_isolate <- function(x = NULL,
col_date = NULL,
col_patient_id = NULL,
col_mo = NULL,
@@ -139,11 +160,42 @@ first_isolate <- function(x,
info = interactive(),
include_unknown = FALSE,
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
x <- tryCatch(get_current_data(arg_name = "x", call = -2), error = function(e) x)
}
meet_criteria(x, allow_class = "data.frame") # also checks dimensions to be >0
meet_criteria(col_date, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_patient_id, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_mo, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_testcode, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
if (isFALSE(col_specimen)) {
col_specimen <- NULL
}
meet_criteria(col_specimen, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_icu, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
if (isFALSE(col_keyantibiotics)) {
col_keyantibiotics <- NULL
}
meet_criteria(col_keyantibiotics, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(episode_days, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(testcodes_exclude, allow_class = "character", allow_NULL = TRUE)
meet_criteria(icu_exclude, allow_class = "logical", has_length = 1)
meet_criteria(specimen_group, allow_class = "character", has_length = 1, allow_NULL = TRUE)
meet_criteria(type, allow_class = "character", has_length = 1)
meet_criteria(ignore_I, allow_class = "logical", has_length = 1)
meet_criteria(points_threshold, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(info, allow_class = "logical", has_length = 1)
meet_criteria(include_unknown, allow_class = "logical", has_length = 1)
# remove data.table, grouping from tibbles, etc.
x <- as.data.frame(x, stringsAsFactors = FALSE)
dots <- unlist(list(...))
if (length(dots) != 0) {
# backwards compatibility with old parameters
dots.names <- dots %pm>% names()
# backwards compatibility with old arguments
dots.names <- names(dots)
if ("filter_specimen" %in% dots.names) {
specimen_group <- dots[which(dots.names == "filter_specimen")]
}
@@ -152,18 +204,11 @@ first_isolate <- function(x,
}
}
stop_ifnot(is.data.frame(x), "`x` must be a data.frame")
stop_if(any(dim(x) == 0), "`x` must contain rows and columns")
# remove data.table, grouping from tibbles, etc.
x <- as.data.frame(x, stringsAsFactors = FALSE)
# try to find columns based on type
# -- mo
if (is.null(col_mo)) {
col_mo <- search_type_in_df(x = x, type = "mo")
stop_if(is.null(col_mo), "`col_mo` must be set")
stop_ifnot(col_mo %in% colnames(x), "column '", col_mo, "' (`col_mo`) not found")
}
# -- date
@@ -178,7 +223,7 @@ first_isolate <- function(x,
# WHONET support
x$patient_id <- paste(x$`First name`, x$`Last name`, x$Sex)
col_patient_id <- "patient_id"
message(font_blue(paste0("NOTE: Using combined columns `", font_bold("First name"), "`, `", font_bold("Last name"), "` and `", font_bold("Sex"), "` as input for `col_patient_id`")))
message_("Using combined columns '", font_bold("First name"), "', '", font_bold("Last name"), "' and '", font_bold("Sex"), "' as input for `col_patient_id`")
} else {
col_patient_id <- search_type_in_df(x = x, type = "patient_id")
}
@@ -189,23 +234,17 @@ first_isolate <- function(x,
if (is.null(col_keyantibiotics)) {
col_keyantibiotics <- search_type_in_df(x = x, type = "keyantibiotics")
}
if (isFALSE(col_keyantibiotics)) {
col_keyantibiotics <- NULL
}
# -- specimen
if (is.null(col_specimen) & !is.null(specimen_group)) {
col_specimen <- search_type_in_df(x = x, type = "specimen")
}
if (isFALSE(col_specimen)) {
col_specimen <- NULL
}
# check if columns exist
check_columns_existance <- function(column, tblname = x) {
if (!is.null(column)) {
stop_ifnot(column %in% colnames(tblname),
"Column `", column, "` not found.", call = FALSE)
"Column '", column, "' not found.", call = FALSE)
}
}
@@ -223,7 +262,7 @@ first_isolate <- function(x,
# create original row index
x$newvar_row_index <- seq_len(nrow(x))
x$newvar_mo <- x[, col_mo, drop = TRUE]
x$newvar_mo <- as.mo(x[, col_mo, drop = TRUE])
x$newvar_genus_species <- paste(mo_genus(x$newvar_mo), mo_species(x$newvar_mo))
x$newvar_date <- x[, col_date, drop = TRUE]
x$newvar_patient_id <- x[, col_patient_id, drop = TRUE]
@@ -233,7 +272,9 @@ first_isolate <- function(x,
}
# remove testcodes
if (!is.null(testcodes_exclude) & info == TRUE) {
message(font_black(paste0("[Criterion] Exclude test codes: ", toString(paste0("'", testcodes_exclude, "'")))))
message_("[Criterion] Exclude test codes: ", toString(paste0("'", testcodes_exclude, "'")),
add_fn = font_black,
as_note = FALSE)
}
if (is.null(col_specimen)) {
@@ -244,7 +285,9 @@ first_isolate <- function(x,
if (!is.null(specimen_group)) {
check_columns_existance(col_specimen, x)
if (info == TRUE) {
message(font_black(paste0("[Criterion] Exclude other than specimen group '", specimen_group, "'")))
message_("[Criterion] Exclude other than specimen group '", specimen_group, "'",
add_fn = font_black,
as_note = FALSE)
}
}
if (!is.null(col_keyantibiotics)) {
@@ -278,13 +321,32 @@ first_isolate <- function(x,
)
}
# no isolates found
# speed up - return immediately if obvious
if (abs(row.start) == Inf | abs(row.end) == Inf) {
if (info == TRUE) {
message(paste("=> Found", font_bold("no isolates")))
message_("=> Found ", font_bold("no isolates"),
add_fn = font_black,
as_note = FALSE)
}
return(rep(FALSE, nrow(x)))
}
if (row.start == row.end) {
if (info == TRUE) {
message_("=> Found ", font_bold("1 isolate"), ", as the data only contained 1 row",
add_fn = font_black,
as_note = FALSE)
}
return(TRUE)
}
if (length(c(row.start:row.end)) == pm_n_distinct(x[c(row.start:row.end), col_mo, drop = TRUE])) {
if (info == TRUE) {
message_("=> Found ", font_bold(paste(length(c(row.start:row.end)), "isolates")),
", as all isolates were different microorganisms",
add_fn = font_black,
as_note = FALSE)
}
return(rep(TRUE, length(c(row.start:row.end))))
}
# did find some isolates - add new index numbers of rows
x$newvar_row_index_sorted <- seq_len(nrow(x))
@@ -292,28 +354,6 @@ first_isolate <- function(x,
scope.size <- nrow(x[which(x$newvar_row_index_sorted %in% c(row.start + 1:row.end) &
!is.na(x$newvar_mo)), , drop = FALSE])
identify_new_year <- function(x, episode_days) {
# I asked on StackOverflow:
# https://stackoverflow.com/questions/42122245/filter-one-row-every-year
if (length(x) == 1) {
return(TRUE)
}
indices <- integer(0)
start <- x[1]
ind <- 1
indices[ind] <- ind
for (i in 2:length(x)) {
if (isTRUE(as.numeric(x[i] - start) >= episode_days)) {
ind <- ind + 1
indices[ind] <- i
start <- x[i]
}
}
result <- rep(FALSE, length(x))
result[indices] <- TRUE
return(result)
}
# Analysis of first isolate ----
x$other_pat_or_mo <- ifelse(x$newvar_patient_id == pm_lag(x$newvar_patient_id) &
x$newvar_genus_species == pm_lag(x$newvar_genus_species),
@@ -324,8 +364,8 @@ first_isolate <- function(x,
function(g,
df = x,
days = episode_days) {
identify_new_year(x = df[which(df$episode_group == g), "newvar_date", drop = TRUE],
episode_days = days)
is_new_episode(x = df[which(df$episode_group == g), ]$newvar_date,
episode_days = days)
}))
weighted.notice <- ""
@@ -333,13 +373,17 @@ first_isolate <- function(x,
weighted.notice <- "weighted "
if (info == TRUE) {
if (type == "keyantibiotics") {
message(font_black(paste0("[Criterion] Base inclusion on key antibiotics, ",
ifelse(ignore_I == FALSE, "not ", ""),
"ignoring I")))
message_("[Criterion] Base inclusion on key antibiotics, ",
ifelse(ignore_I == FALSE, "not ", ""),
"ignoring I",
add_fn = font_black,
as_note = FALSE)
}
if (type == "points") {
message(font_black(paste0("[Criterion] Base inclusion on key antibiotics, using points threshold of "
, points_threshold)))
message_("[Criterion] Base inclusion on key antibiotics, using points threshold of "
, points_threshold,
add_fn = font_black,
as_note = FALSE)
}
}
type_param <- type
@@ -352,20 +396,20 @@ first_isolate <- function(x,
info = info)
# with key antibiotics
x$newvar_first_isolate <- pm_if_else(x$newvar_row_index_sorted >= row.start &
x$newvar_row_index_sorted <= row.end &
x$newvar_genus_species != "" &
(x$other_pat_or_mo | x$more_than_episode_ago | x$other_key_ab),
TRUE,
FALSE)
x$newvar_row_index_sorted <= row.end &
x$newvar_genus_species != "" &
(x$other_pat_or_mo | x$more_than_episode_ago | x$other_key_ab),
TRUE,
FALSE)
} else {
# no key antibiotics
x$newvar_first_isolate <- pm_if_else(x$newvar_row_index_sorted >= row.start &
x$newvar_row_index_sorted <= row.end &
x$newvar_genus_species != "" &
(x$other_pat_or_mo | x$more_than_episode_ago),
TRUE,
FALSE)
x$newvar_row_index_sorted <= row.end &
x$newvar_genus_species != "" &
(x$other_pat_or_mo | x$more_than_episode_ago),
TRUE,
FALSE)
}
# first one as TRUE
@@ -376,30 +420,55 @@ first_isolate <- function(x,
}
if (!is.null(col_icu)) {
if (icu_exclude == TRUE) {
message(font_black("[Criterion] Exclude isolates from ICU.\n"))
message_("[Criterion] Exclude isolates from ICU.",
add_fn = font_black,
as_note = FALSE)
x[which(as.logical(x[, col_icu, drop = TRUE])), "newvar_first_isolate"] <- FALSE
} else {
message(font_black("[Criterion] Include isolates from ICU.\n"))
message_("[Criterion] Include isolates from ICU.",
add_fn = font_black,
as_note = FALSE)
}
}
decimal.mark <- getOption("OutDec")
big.mark <- ifelse(decimal.mark != ",", ",", ".")
if (info == TRUE) {
# print group name if used in dplyr::group_by()
cur_group <- import_fn("cur_group", "dplyr", error_on_fail = FALSE)
if (!is.null(cur_group)) {
group_df <- tryCatch(cur_group(), error = function(e) data.frame())
if (NCOL(group_df) > 0) {
# transform factors to characters
group <- vapply(FUN.VALUE = character(1), group_df, function(x) {
if (is.numeric(x)) {
format(x)
} else if (is.logical(x)) {
as.character(x)
} else {
paste0('"', x, '"')
}
})
cat("\nGroup: ", paste0(names(group), " = ", group, collapse = ", "), "\n", sep = "")
}
}
}
# handle empty microorganisms
if (any(x$newvar_mo == "UNKNOWN", na.rm = TRUE) & info == TRUE) {
message(font_blue(paste0("NOTE: ", ifelse(include_unknown == TRUE, "Included ", "Excluded "),
format(sum(x$newvar_mo == "UNKNOWN", na.rm = TRUE),
decimal.mark = decimal.mark, big.mark = big.mark),
" isolates with a microbial ID 'UNKNOWN' (column `", font_bold(col_mo), "`)")))
message_(ifelse(include_unknown == TRUE, "Included ", "Excluded "),
format(sum(x$newvar_mo == "UNKNOWN", na.rm = TRUE),
decimal.mark = decimal.mark, big.mark = big.mark),
" isolates with a microbial ID 'UNKNOWN' (in column '", font_bold(col_mo), "')")
}
x[which(x$newvar_mo == "UNKNOWN"), "newvar_first_isolate"] <- include_unknown
# exclude all NAs
if (any(is.na(x$newvar_mo)) & info == TRUE) {
message(font_blue(paste0("NOTE: Excluded ", format(sum(is.na(x$newvar_mo), na.rm = TRUE),
decimal.mark = decimal.mark, big.mark = big.mark),
" isolates with a microbial ID 'NA' (column `", font_bold(col_mo), "`)")))
message_("Excluded ", format(sum(is.na(x$newvar_mo), na.rm = TRUE),
decimal.mark = decimal.mark, big.mark = big.mark),
" isolates with a microbial ID 'NA' (in column '", font_bold(col_mo), "')")
}
x[which(is.na(x$newvar_mo)), "newvar_first_isolate"] <- FALSE
@@ -428,7 +497,7 @@ first_isolate <- function(x,
font_bold(paste0(n_found, " first ", weighted.notice, "isolates")),
" (", p_found_total, " of total where a microbial ID was available)")
}
message(font_black(msg_txt))
message_(msg_txt, add_fn = font_black, as_note = FALSE)
}
x$newvar_first_isolate
@@ -437,11 +506,21 @@ first_isolate <- function(x,
#' @rdname first_isolate
#' @export
filter_first_isolate <- function(x,
filter_first_isolate <- function(x = NULL,
col_date = NULL,
col_patient_id = NULL,
col_mo = NULL,
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
x <- tryCatch(get_current_data(arg_name = "x", call = -2), error = function(e) x)
}
meet_criteria(x, allow_class = "data.frame") # also checks dimensions to be >0
meet_criteria(col_date, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_patient_id, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_mo, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
subset(x, first_isolate(x = x,
col_date = col_date,
col_patient_id = col_patient_id,
@@ -451,12 +530,23 @@ filter_first_isolate <- function(x,
#' @rdname first_isolate
#' @export
filter_first_weighted_isolate <- function(x,
filter_first_weighted_isolate <- function(x = NULL,
col_date = NULL,
col_patient_id = NULL,
col_mo = NULL,
col_keyantibiotics = NULL,
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
x <- tryCatch(get_current_data(arg_name = "x", call = -2), error = function(e) x)
}
meet_criteria(x, allow_class = "data.frame") # also checks dimensions to be >0
meet_criteria(col_date, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_patient_id, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_mo, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
meet_criteria(col_keyantibiotics, allow_class = "character", has_length = 1, allow_NULL = TRUE, is_in = colnames(x))
y <- x
if (is.null(col_keyantibiotics)) {
# first try to look for it
@@ -472,8 +562,5 @@ filter_first_weighted_isolate <- function(x,
subset(x, first_isolate(x = y,
col_date = col_date,
col_patient_id = col_patient_id,
col_mo = col_mo,
col_keyantibiotics = col_keyantibiotics,
...))
col_patient_id = col_patient_id))
}
+11 -11
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,13 +20,13 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' *G*-test for Count Data
#'
#' [g.test()] performs chi-squared contingency table tests and goodness-of-fit tests, just like [chisq.test()] but is more reliable (1). A *G*-test can be used to see whether the number of observations in each category fits a theoretical expectation (called a ***G*-test of goodness-of-fit**), or to see whether the proportions of one variable are different for different values of the other variable (called a ***G*-test of independence**).
#' @inheritSection lifecycle Questioning lifecycle
#' @inheritSection lifecycle Questioning Lifecycle
#' @inherit stats::chisq.test params return
#' @details If `x` is a matrix with one row or column, or if `x` is a vector and `y` is not given, then a *goodness-of-fit test* is performed (`x` is treated as a one-dimensional contingency table). The entries of `x` must be non-negative integers. In this case, the hypothesis tested is whether the population probabilities equal those in `p`, or are all equal if `p` is not given.
#'
@@ -34,18 +34,18 @@
#'
#' The p-value is computed from the asymptotic chi-squared distribution of the test statistic.
#'
#' In the contingency table case simulation is done by random sampling from the set of all contingency tables with given marginals, and works only if the marginals are strictly positive. Note that this is not the usual sampling situation assumed for a chi-squared test (like the *G*-test) but rather that for Fisher's exact test.
#' In the contingency table case simulation is done by random sampling from the set of all contingency tables with given marginals, and works only if the marginals are strictly positive. Note that this is not the usual sampling situation assumed for a chi-squared test (such as the *G*-test) but rather that for Fisher's exact test.
#'
#' In the goodness-of-fit case simulation is done by random sampling from the discrete distribution specified by `p`, each sample being of size `n = sum(x)`. This simulation is done in \R and may be slow.
#'
#' ## *G*-test of goodness-of-fit (likelihood ratio test)
#' ## *G*-test Of Goodness-of-Fit (Likelihood Ratio Test)
#' Use the *G*-test of goodness-of-fit when you have one nominal variable with two or more values (such as male and female, or red, pink and white flowers). You compare the observed counts of numbers of observations in each category with the expected counts, which you calculate using some kind of theoretical expectation (such as a 1:1 sex ratio or a 1:2:1 ratio in a genetic cross).
#'
#' If the expected number of observations in any category is too small, the *G*-test may give inaccurate results, and you should use an exact test instead ([fisher.test()]).
#'
#' The *G*-test of goodness-of-fit is an alternative to the chi-square test of goodness-of-fit ([chisq.test()]); each of these tests has some advantages and some disadvantages, and the results of the two tests are usually very similar.
#'
#' ## *G*-test of independence
#' ## *G*-test of Independence
#' Use the *G*-test of independence when you have two nominal variables, each with two or more possible values. You want to know whether the proportions for one variable are different among values of the other variable.
#'
#' It is also possible to do a *G*-test of independence with more than two nominal variables. For example, Jackson et al. (2013) also had data for children under 3, so you could do an analysis of old vs. young, thigh vs. arm, and reaction vs. no reaction, all analyzed together.
@@ -54,7 +54,7 @@
#'
#' The *G*-test of independence is an alternative to the chi-square test of independence ([chisq.test()]), and they will give approximately the same results.
#'
#' ## How the test works
#' ## How the Test Works
#' Unlike the exact test of goodness-of-fit ([fisher.test()]), the *G*-test does not directly calculate the probability of obtaining the observed results or something more extreme. Instead, like almost all statistical tests, the *G*-test has an intermediate step; it uses the data to calculate a test statistic that measures how far the observed data are from the null expectation. You then use a mathematical relationship, in this case the chi-square distribution, to estimate the probability of obtaining that value of the test statistic.
#'
#' The *G*-test uses the log of the ratio of two likelihoods as the test statistic, which is why it is also called a likelihood ratio test or log-likelihood ratio test. The formula to calculate a *G*-statistic is:
@@ -76,7 +76,7 @@
#' - The possibility to simulate p values with `simulate.p.value` was removed
#' @export
#' @importFrom stats pchisq complete.cases
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # = EXAMPLE 1 =
#' # Shivrain et al. (2006) crossed clearfield rice (which are resistant
@@ -144,7 +144,7 @@ g.test <- function(x,
DNAME <- paste(paste(DNAME, collapse = "\n"), "and",
paste(DNAME2, collapse = "\n"))
}
if (any(x < 0) || anyNA(x))
if (any(x < 0) || any(is.na((x)))) # this last one was anyNA, but only introduced in R 3.1.0
stop("all entries of 'x' must be nonnegative and finite")
if ((n <- sum(x)) == 0)
stop("at least one entry of 'x' must be positive")
@@ -200,7 +200,7 @@ g.test <- function(x,
if (any(E < 5) && is.finite(PARAMETER))
warning("G-statistic approximation may be incorrect due to E < 5")
structure(list(statistic = STATISTIC, parameter = PARAMETER,
structure(list(statistic = STATISTIC, argument = PARAMETER,
p.value = PVAL, method = METHOD, data.name = DNAME,
observed = x, expected = E, residuals = (x - E) / sqrt(E),
stdres = (x - E) / sqrt(V)), class = "htest")
+40 -32
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,13 +20,13 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' PCA biplot with `ggplot2`
#' PCA Biplot with `ggplot2`
#'
#' Produces a `ggplot2` variant of a so-called [biplot](https://en.wikipedia.org/wiki/Biplot) for PCA (principal component analysis), but is more flexible and more appealing than the base \R [biplot()] function.
#' @inheritSection lifecycle Maturing lifecycle
#' @inheritSection lifecycle Maturing Lifecycle
#' @param x an object returned by [pca()], [prcomp()] or [princomp()]
#' @inheritParams stats::biplot.prcomp
#' @param labels an optional vector of labels for the observations. If set, the labels will be placed below their respective points. When using the [pca()] function as input for `x`, this will be determined automatically based on the attribute `non_numeric_cols`, see [pca()].
@@ -47,20 +47,21 @@
#' @param arrows_textangled a logical whether the text at the end of the arrows should be angled
#' @param arrows_alpha the alpha (transparency) of the arrows and their text
#' @param base_textsize the text size for all plot elements except the labels and arrows
#' @param ... Parameters passed on to functions
#' @param ... Arguments passed on to functions
#' @source The [ggplot_pca()] function is based on the `ggbiplot()` function from the `ggbiplot` package by Vince Vu, as found on GitHub: <https://github.com/vqv/ggbiplot> (retrieved: 2 March 2020, their latest commit: [`7325e88`](https://github.com/vqv/ggbiplot/commit/7325e880485bea4c07465a0304c470608fffb5d9); 12 February 2015).
#'
#' As per their GPL-2 licence that demands documentation of code changes, the changes made based on the source code were:
#' 1. Rewritten code to remove the dependency on packages `plyr`, `scales` and `grid`
#' 2. Parametrised more options, like arrow and ellipse settings
#' 3. Added total amount of explained variance as a caption in the plot
#' 4. Cleaned all syntax based on the `lintr` package and added integrity checks
#' 5. Updated documentation
#' 3. Hardened all input possibilities by defining the exact type of user input for every argument
#' 4. Added total amount of explained variance as a caption in the plot
#' 5. Cleaned all syntax based on the `lintr` package, fixed grammatical errors and added integrity checks
#' 6. Updated documentation
#' @details The colours for labels and points can be changed by adding another scale layer for colour, like `scale_colour_viridis_d()` or `scale_colour_brewer()`.
#' @rdname ggplot_pca
#' @export
#' @examples
#' # `example_isolates` is a dataset available in the AMR package.
#' # `example_isolates` is a data set available in the AMR package.
#' # See ?example_isolates.
#'
#' # See ?pca for more info about Principal Component Analysis (PCA).
@@ -85,7 +86,7 @@
#' }
ggplot_pca <- function(x,
choices = 1:2,
scale = TRUE,
scale = 1,
pc.biplot = TRUE,
labels = NULL,
labels_textsize = 3,
@@ -107,22 +108,27 @@ ggplot_pca <- function(x,
...) {
stop_ifnot_installed("ggplot2")
stop_ifnot(length(choices) == 2, "`choices` must be of length 2")
stop_ifnot(is.logical(arrows), "`arrows` must be TRUE or FALSE")
stop_ifnot(is.logical(arrows_textangled), "`arrows_textangled` must be TRUE or FALSE")
stop_ifnot(is.logical(ellipse), "`ellipse` must be TRUE or FALSE")
stop_ifnot(is.logical(pc.biplot), "`pc.biplot` must be TRUE or FALSE")
stop_ifnot(is.logical(scale), "`scale` must be TRUE or FALSE")
stop_ifnot(is.numeric(arrows_alpha), "`arrows_alpha` must be numeric")
stop_ifnot(is.numeric(arrows_size), "`arrows_size` must be numeric")
stop_ifnot(is.numeric(arrows_textsize), "`arrows_textsize` must be numeric")
stop_ifnot(is.numeric(base_textsize), "`base_textsize` must be numeric")
stop_ifnot(is.numeric(choices), "`choices` must be numeric")
stop_ifnot(is.numeric(ellipse_alpha), "`ellipse_alpha` must be numeric")
stop_ifnot(is.numeric(ellipse_prob), "`ellipse_prob` must be numeric")
stop_ifnot(is.numeric(ellipse_size), "`ellipse_size` must be numeric")
stop_ifnot(is.numeric(labels_text_placement), "`labels_text_placement` must be numeric")
stop_ifnot(is.numeric(labels_textsize), "`labels_textsize` must be numeric")
meet_criteria(x, allow_class = c("prcomp", "princomp", "PCA", "lda"))
meet_criteria(choices, allow_class = c("numeric", "integer"), has_length = 2, is_positive = TRUE, is_finite = TRUE)
meet_criteria(scale, allow_class = c("numeric", "integer", "logical"), has_length = 1)
meet_criteria(pc.biplot, allow_class = "logical", has_length = 1)
meet_criteria(labels, allow_class = "character", allow_NULL = TRUE)
meet_criteria(labels_textsize, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(labels_text_placement, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(groups, allow_class = "character", allow_NULL = TRUE)
meet_criteria(ellipse, allow_class = "logical", has_length = 1)
meet_criteria(ellipse_prob, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(ellipse_size, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(ellipse_alpha, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(points_size, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(points_alpha, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(arrows, allow_class = "logical", has_length = 1)
meet_criteria(arrows_colour, allow_class = "character", has_length = 1)
meet_criteria(arrows_size, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(arrows_textsize, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(arrows_textangled, allow_class = "logical", has_length = 1)
meet_criteria(arrows_alpha, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(base_textsize, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
calculations <- pca_calculations(pca_model = x,
groups = groups,
@@ -300,19 +306,20 @@ pca_calculations <- function(pca_model,
d <- pca_model$svd
u <- predict(pca_model)$x / nobs.factor
v <- pca_model$scaling
d.total <- sum(d ^ 2)
} else {
stop("Expected a object of class prcomp, princomp, PCA, or lda")
stop("Expected an object of class prcomp, princomp, PCA, or lda")
}
# Scores
choices <- pmin(choices, ncol(u))
obs.scale <- 1 - as.integer(scale)
df.u <- as.data.frame(sweep(u[, choices], 2, d[choices] ^ obs.scale, FUN = "*"))
df.u <- as.data.frame(sweep(u[, choices], 2, d[choices] ^ obs.scale, FUN = "*"),
stringsAsFactors = FALSE)
# Directions
v <- sweep(v, 2, d ^ as.integer(scale), FUN = "*")
df.v <- as.data.frame(v[, choices])
df.v <- as.data.frame(v[, choices],
stringsAsFactors = FALSE)
names(df.u) <- c("xvar", "yvar")
names(df.v) <- names(df.u)
@@ -350,7 +357,8 @@ pca_calculations <- function(pca_model,
if (nrow(x) <= 2) {
return(data.frame(X1 = numeric(0),
X2 = numeric(0),
groups = character(0)))
groups = character(0),
stringsAsFactors = FALSE))
}
sigma <- var(cbind(x$xvar, x$yvar))
mu <- c(mean(x$xvar), mean(x$yvar))
+68 -30
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,13 +20,13 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' AMR plots with `ggplot2`
#' AMR Plots with `ggplot2`
#'
#' Use these functions to create bar plots for antimicrobial resistance analysis. All functions rely on [ggplot2][ggplot2::ggplot()] functions.
#' @inheritSection lifecycle Maturing lifecycle
#' Use these functions to create bar plots for AMR data analysis. All functions rely on [ggplot2][ggplot2::ggplot()] functions.
#' @inheritSection lifecycle Maturing Lifecycle
#' @param data a [data.frame] with column(s) of class [`rsi`] (see [as.rsi()])
#' @param position position adjustment of bars, either `"fill"`, `"stack"` or `"dodge"`
#' @param x variable to show on x axis, either `"antibiotic"` (default) or `"interpretation"` or a grouping variable
@@ -36,7 +36,7 @@
#' @param facet variable to split plots by, either `"interpretation"` (default) or `"antibiotic"` or a grouping variable
#' @inheritParams proportion
#' @param nrow (when using `facet`) number of rows
#' @param colours a named vector with colours for the bars. The names must be one or more of: S, SI, I, IR, R or be `FALSE` to use default [ggplot2][[ggplot2::ggplot()] colours.
#' @param colours a named vector with colours for the bars. The names must be one or more of: S, SI, I, IR, R or be `FALSE` to use default [ggplot2][ggplot2::ggplot()] colours.
#' @param datalabels show datalabels using [labels_rsi_count()]
#' @param datalabels.size size of the datalabels
#' @param datalabels.colour colour of the datalabels
@@ -45,10 +45,10 @@
#' @param caption text to show as caption of the plot
#' @param x.title text to show as x axis description
#' @param y.title text to show as y axis description
#' @param ... other parameters passed on to [geom_rsi()]
#' @details At default, the names of antibiotics will be shown on the plots using [ab_name()]. This can be set with the `translate_ab` parameter. See [count_df()].
#' @param ... other arguments passed on to [geom_rsi()]
#' @details At default, the names of antibiotics will be shown on the plots using [ab_name()]. This can be set with the `translate_ab` argument. See [count_df()].
#'
#' ## The functions
#' ## The Functions
#' [geom_rsi()] will take any variable from the data that has an [`rsi`] class (created with [as.rsi()]) using [rsi_df()] and will plot bars with the percentage R, I and S. The default behaviour is to have the bars stacked and to have the different antibiotics on the x axis.
#'
#' [facet_rsi()] creates 2d plots (at default based on S/I/R) using [ggplot2::facet_wrap()].
@@ -61,10 +61,10 @@
#'
#' [labels_rsi_count()] print datalabels on the bars with percentage and amount of isolates using [ggplot2::geom_text()].
#'
#' [ggplot_rsi()] is a wrapper around all above functions that uses data as first input. This makes it possible to use this function after a pipe (`%>%`). See Examples.
#' [ggplot_rsi()] is a wrapper around all above functions that uses data as first input. This makes it possible to use this function after a pipe (`%>%`). See *Examples*.
#' @rdname ggplot_rsi
#' @export
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' if (require("ggplot2") & require("dplyr")) {
#'
@@ -91,7 +91,7 @@
#' select(AMX, NIT, FOS, TMP, CIP) %>%
#' ggplot_rsi(datalabels = FALSE)
#'
#' # add other ggplot2 parameters as you like:
#' # add other ggplot2 arguments as you like:
#' example_isolates %>%
#' select(AMX, NIT, FOS, TMP, CIP) %>%
#' ggplot_rsi(width = 0.5,
@@ -107,13 +107,12 @@
#' }
#'
#' \donttest{
#'
#' # resistance of ciprofloxacine per age group
#' example_isolates %>%
#' mutate(first_isolate = first_isolate(.)) %>%
#' filter(first_isolate == TRUE,
#' mo == as.mo("E. coli")) %>%
#' # `age_groups` is also a function of this AMR package:
#' # age_groups() is also a function in this AMR package:
#' group_by(age_group = age_groups(age)) %>%
#' select(age_group,
#' CIP) %>%
@@ -162,7 +161,7 @@ ggplot_rsi <- function(data,
R = "#ff6961"),
datalabels = TRUE,
datalabels.size = 2.5,
datalabels.colour = "gray15",
datalabels.colour = "grey15",
title = NULL,
subtitle = NULL,
caption = NULL,
@@ -171,10 +170,29 @@ ggplot_rsi <- function(data,
...) {
stop_ifnot_installed("ggplot2")
x <- x[1]
facet <- facet[1]
meet_criteria(data, allow_class = "data.frame", contains_column_class = "rsi")
meet_criteria(position, allow_class = "character", has_length = 1, is_in = c("fill", "stack", "dodge"), allow_NULL = TRUE)
meet_criteria(x, allow_class = "character", has_length = 1)
meet_criteria(fill, allow_class = "character", has_length = 1)
meet_criteria(facet, allow_class = "character", has_length = 1, allow_NULL = TRUE)
meet_criteria(breaks, allow_class = c("numeric", "integer"))
meet_criteria(limits, allow_class = c("numeric", "integer"), has_length = 2, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(translate_ab, allow_class = c("character", "logical"), has_length = 1, allow_NA = TRUE)
meet_criteria(combine_SI, allow_class = "logical", has_length = 1)
meet_criteria(combine_IR, allow_class = "logical", has_length = 1)
meet_criteria(minimum, allow_class = c("numeric", "integer"), has_length = 1, is_finite = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(nrow, allow_class = c("numeric", "integer"), has_length = 1, allow_NULL = TRUE, is_positive = TRUE, is_finite = TRUE)
meet_criteria(colours, allow_class = c("character", "logical"))
meet_criteria(datalabels, allow_class = "logical", has_length = 1)
meet_criteria(datalabels.size, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(datalabels.colour, allow_class = "character", has_length = 1)
meet_criteria(title, allow_class = "character", has_length = 1, allow_NULL = TRUE)
meet_criteria(subtitle, allow_class = "character", has_length = 1, allow_NULL = TRUE)
meet_criteria(caption, allow_class = "character", has_length = 1, allow_NULL = TRUE)
meet_criteria(x.title, allow_class = "character", has_length = 1, allow_NULL = TRUE)
meet_criteria(y.title, allow_class = "character", has_length = 1, allow_NULL = TRUE)
# we work with aes_string later on
x_deparse <- deparse(substitute(x))
if (x_deparse != "x") {
@@ -207,8 +225,8 @@ ggplot_rsi <- function(data,
if (fill == "interpretation") {
# set RSI colours
if (isFALSE(colours) & missing(datalabels.colour)) {
# set datalabel colour to middle gray
datalabels.colour <- "gray50"
# set datalabel colour to middle grey
datalabels.colour <- "grey50"
}
p <- p + scale_rsi_colours(colours = colours)
}
@@ -254,9 +272,17 @@ geom_rsi <- function(position = NULL,
combine_SI = TRUE,
combine_IR = FALSE,
...) {
x <- x[1]
stop_ifnot_installed("ggplot2")
stop_if(is.data.frame(position), "`position` is invalid. Did you accidentally use '%pm>%' instead of '+'?")
stop_if(is.data.frame(position), "`position` is invalid. Did you accidentally use '%>%' instead of '+'?")
meet_criteria(position, allow_class = "character", has_length = 1, is_in = c("fill", "stack", "dodge"), allow_NULL = TRUE)
meet_criteria(x, allow_class = "character", has_length = 1)
meet_criteria(fill, allow_class = "character", has_length = 1)
meet_criteria(translate_ab, allow_class = c("character", "logical"), has_length = 1, allow_NA = TRUE)
meet_criteria(minimum, allow_class = c("numeric", "integer"), has_length = 1, is_finite = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(combine_SI, allow_class = "logical", has_length = 1)
meet_criteria(combine_IR, allow_class = "logical", has_length = 1)
y <- "value"
if (missing(position) | is.null(position)) {
@@ -267,8 +293,6 @@ geom_rsi <- function(position = NULL,
position <- ggplot2::position_fill(vjust = 0.5, reverse = TRUE)
}
x <- x[1]
# we work with aes_string later on
x_deparse <- deparse(substitute(x))
if (x_deparse != "x") {
@@ -300,10 +324,10 @@ geom_rsi <- function(position = NULL,
#' @rdname ggplot_rsi
#' @export
facet_rsi <- function(facet = c("interpretation", "antibiotic"), nrow = NULL) {
stop_ifnot_installed("ggplot2")
facet <- facet[1]
stop_ifnot_installed("ggplot2")
meet_criteria(facet, allow_class = "character", has_length = 1)
meet_criteria(nrow, allow_class = c("numeric", "integer"), has_length = 1, allow_NULL = TRUE, is_positive = TRUE, is_finite = TRUE)
# we work with aes_string later on
facet_deparse <- deparse(substitute(facet))
@@ -327,6 +351,8 @@ facet_rsi <- function(facet = c("interpretation", "antibiotic"), nrow = NULL) {
#' @export
scale_y_percent <- function(breaks = seq(0, 1, 0.1), limits = NULL) {
stop_ifnot_installed("ggplot2")
meet_criteria(breaks, allow_class = c("numeric", "integer"))
meet_criteria(limits, allow_class = c("numeric", "integer"), has_length = 2, allow_NULL = TRUE, allow_NA = TRUE)
if (all(breaks[breaks != 0] > 1)) {
breaks <- breaks / 100
@@ -344,6 +370,8 @@ scale_rsi_colours <- function(colours = c(S = "#61a8ff",
IR = "#ff6961",
R = "#ff6961")) {
stop_ifnot_installed("ggplot2")
meet_criteria(colours, allow_class = c("character", "logical"))
# previous colour: palette = "RdYlGn"
# previous colours: values = c("#b22222", "#ae9c20", "#7cfc00")
@@ -381,8 +409,18 @@ labels_rsi_count <- function(position = NULL,
combine_SI = TRUE,
combine_IR = FALSE,
datalabels.size = 3,
datalabels.colour = "gray15") {
datalabels.colour = "grey15") {
stop_ifnot_installed("ggplot2")
meet_criteria(position, allow_class = "character", has_length = 1, is_in = c("fill", "stack", "dodge"), allow_NULL = TRUE)
meet_criteria(x, allow_class = "character", has_length = 1)
meet_criteria(translate_ab, allow_class = c("character", "logical"), has_length = 1, allow_NA = TRUE)
meet_criteria(minimum, allow_class = c("numeric", "integer"), has_length = 1, is_finite = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(combine_SI, allow_class = "logical", has_length = 1)
meet_criteria(combine_IR, allow_class = "logical", has_length = 1)
meet_criteria(datalabels.size, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(datalabels.colour, allow_class = "character", has_length = 1)
if (is.null(position)) {
position <- "fill"
}
+12 -3
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,12 +20,13 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
globalVariables(c(".rowid",
"ab",
"ab_txt",
"affect_mo_name",
"angle",
"antibiotic",
"antibiotics",
@@ -33,12 +34,16 @@ globalVariables(c(".rowid",
"atc_group2",
"code",
"data",
"dosage",
"dose",
"dose_times",
"fullname",
"fullname_lower",
"g_species",
"genus",
"gr",
"group",
"guideline",
"hjust",
"input",
"intrinsic_resistant",
@@ -46,6 +51,7 @@ globalVariables(c(".rowid",
"lang",
"language",
"lookup",
"method",
"microorganism",
"microorganisms",
"microorganisms.codes",
@@ -58,6 +64,7 @@ globalVariables(c(".rowid",
"old_name",
"pattern",
"R",
"reference.rule",
"reference.rule_group",
"reference.version",
"rsi_translation",
@@ -70,8 +77,10 @@ globalVariables(c(".rowid",
"species_id",
"total",
"txt",
"type",
"value",
"varname",
"xvar",
"y",
"year",
"yvar"))
+85 -86
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,20 +20,21 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Guess antibiotic column
#' Guess Antibiotic Column
#'
#' This tries to find a column name in a data set based on information from the [antibiotics] data set. Also supports WHONET abbreviations.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a [data.frame]
#' @param search_string a text to search `x` for, will be checked with [as.ab()] if this value is not a column in `x`
#' @param verbose a logical to indicate whether additional info should be printed
#' @details You can look for an antibiotic (trade) name or abbreviation and it will search `x` and the [antibiotics] data set for any column containing a name or code of that antibiotic. **Longer columns names take precendence over shorter column names.**
#' @param only_rsi_columns a logical to indicate whether only antibiotic columns must be detected that were [transformed to class `<rsi>`]([rsi]) on beforehand (defaults to `FALSE`)
#' @details You can look for an antibiotic (trade) name or abbreviation and it will search `x` and the [antibiotics] data set for any column containing a name or code of that antibiotic. **Longer columns names take precedence over shorter column names.**
#' @return A column name of `x`, or `NULL` when no result is found.
#' @export
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' df <- data.frame(amox = "S",
#' tetr = "R")
@@ -44,7 +45,7 @@
#' # [1] "tetr"
#'
#' guess_ab_col(df, "J01AA07", verbose = TRUE)
#' # NOTE: Using column `tetr` as input for `J01AA07` (tetracycline).
#' # NOTE: Using column 'tetr' as input for J01AA07 (tetracycline).
#' # [1] "tetr"
#'
#' # WHONET codes
@@ -62,49 +63,34 @@
#' AMP_ED20 = "S")
#' guess_ab_col(df, "ampicillin")
#' # [1] "AMP_ED20"
guess_ab_col <- function(x = NULL, search_string = NULL, verbose = FALSE) {
guess_ab_col <- function(x = NULL, search_string = NULL, verbose = FALSE, only_rsi_columns = FALSE) {
meet_criteria(x, allow_class = "data.frame", allow_NULL = TRUE)
meet_criteria(search_string, allow_class = "character", has_length = 1, allow_NULL = TRUE)
meet_criteria(verbose, allow_class = "logical", has_length = 1)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
if (is.null(x) & is.null(search_string)) {
return(as.name("guess_ab_col"))
}
stop_ifnot(is.data.frame(x), "`x` must be a data.frame")
if (length(search_string) > 1) {
warning("argument 'search_string' has length > 1 and only the first element will be used")
search_string <- search_string[1]
}
search_string <- as.character(search_string)
if (search_string %in% colnames(x)) {
ab_result <- search_string
} else {
search_string.ab <- suppressWarnings(as.ab(search_string))
if (search_string.ab %in% colnames(x)) {
ab_result <- colnames(x)[colnames(x) == search_string.ab][1L]
} else if (any(tolower(colnames(x)) %in% tolower(unlist(ab_property(search_string.ab, "abbreviations", language = NULL))))) {
ab_result <- colnames(x)[tolower(colnames(x)) %in% tolower(unlist(ab_property(search_string.ab, "abbreviations", language = NULL)))][1L]
} else {
# sort colnames on length - longest first
cols <- colnames(x[, x %pm>% colnames() %pm>% nchar() %pm>% order() %pm>% rev()])
df_trans <- data.frame(cols = cols,
abs = suppressWarnings(as.ab(cols)),
stringsAsFactors = FALSE)
ab_result <- df_trans[which(df_trans$abs == search_string.ab), "cols"]
ab_result <- ab_result[!is.na(ab_result)][1L]
}
meet_criteria(search_string, allow_class = "character", has_length = 1, allow_NULL = FALSE)
}
all_found <- get_column_abx(x, info = verbose, only_rsi_columns = only_rsi_columns, verbose = verbose)
search_string.ab <- suppressWarnings(as.ab(search_string))
ab_result <- unname(all_found[names(all_found) == search_string.ab])
if (length(ab_result) == 0) {
if (verbose == TRUE) {
message(paste0("No column found as input for `", search_string,
"` (", ab_name(search_string, language = NULL, tolower = TRUE), ")."))
message_("No column found as input for ", search_string,
" (", ab_name(search_string, language = NULL, tolower = TRUE), ").",
add_fn = font_black,
as_note = FALSE)
}
return(NULL)
} else {
if (verbose == TRUE) {
message(font_blue(paste0("NOTE: Using column `", font_bold(ab_result), "` as input for `", search_string,
"` (", ab_name(search_string, language = NULL, tolower = TRUE), ").")))
message_("Using column '", font_bold(ab_result), "' as input for ", search_string,
" (", ab_name(search_string, language = NULL, tolower = TRUE), ").")
}
return(ab_result)
}
@@ -115,54 +101,72 @@ get_column_abx <- function(x,
hard_dependencies = NULL,
verbose = FALSE,
info = TRUE,
only_rsi_columns = FALSE,
...) {
meet_criteria(x, allow_class = "data.frame")
meet_criteria(soft_dependencies, allow_class = "character", allow_NULL = TRUE)
meet_criteria(hard_dependencies, allow_class = "character", allow_NULL = TRUE)
meet_criteria(verbose, allow_class = "logical", has_length = 1)
meet_criteria(info, allow_class = "logical", has_length = 1)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
if (info == TRUE) {
message(font_blue("NOTE: Auto-guessing columns suitable for analysis"), appendLF = FALSE)
message_("Auto-guessing columns suitable for analysis", appendLF = FALSE, as_note = FALSE)
}
x <- as.data.frame(x, stringsAsFactors = FALSE)
if (only_rsi_columns == TRUE) {
x <- x[, which(is.rsi(x)), drop = FALSE]
}
if (NROW(x) > 10000) {
# only test maximum of 10,000 values per column
if (info == TRUE) {
message(font_blue(paste0(" (using only ", font_bold("the first 10,000 rows"), ")...")), appendLF = FALSE)
message_(" (using only ", font_bold("the first 10,000 rows"), ")...",
appendLF = FALSE,
as_note = FALSE)
}
x <- x[1:10000, , drop = FALSE]
} else if (info == TRUE) {
message(font_blue("..."), appendLF = FALSE)
message_("...", appendLF = FALSE, as_note = FALSE)
}
x_bak <- x
# only check columns that are a valid AB code, ATC code, name, abbreviation or synonym,
# or already have the rsi class (as.rsi)
# and that have no more than 50% invalid values
vectr_antibiotics <- unique(toupper(unlist(antibiotics[, c("ab", "atc", "name", "abbreviations", "synonyms")])))
# or already have the <rsi> class (as.rsi)
# and that they have no more than 50% invalid values
vectr_antibiotics <- unlist(AB_lookup$generalised_all)
vectr_antibiotics <- vectr_antibiotics[!is.na(vectr_antibiotics) & nchar(vectr_antibiotics) >= 3]
x_columns <- sapply(colnames(x), function(col, df = x_bak) {
if (toupper(col) %in% vectr_antibiotics |
is.rsi(as.data.frame(df)[, col, drop = TRUE]) |
is.rsi.eligible(as.data.frame(df)[, col, drop = TRUE], threshold = 0.5)) {
return(col)
} else {
return(NA_character_)
}
})
x_columns <- x_columns[!is.na(x_columns)]
x <- x[, x_columns, drop = FALSE] # without drop = TRUE, x will become a vector when x_columns is length 1
x_columns <- vapply(FUN.VALUE = character(1),
colnames(x),
function(col, df = x) {
if (generalise_antibiotic_name(col) %in% vectr_antibiotics ||
is.rsi(x[, col, drop = TRUE]) ||
is.rsi.eligible(x[, col, drop = TRUE], threshold = 0.5)
) {
return(col)
} else {
return(NA_character_)
}
})
x_columns <- x_columns[!is.na(x_columns)]
x <- x[, x_columns, drop = FALSE] # without drop = FALSE, x will become a vector when x_columns is length 1
df_trans <- data.frame(colnames = colnames(x),
abcode = suppressWarnings(as.ab(colnames(x), info = FALSE)))
abcode = suppressWarnings(as.ab(colnames(x), info = FALSE)),
stringsAsFactors = FALSE)
df_trans <- df_trans[!is.na(df_trans$abcode), , drop = FALSE]
x <- as.character(df_trans$colnames)
names(x) <- df_trans$abcode
# add from self-defined dots (...):
# such as get_column_abx(example_isolates %pm>% rename(thisone = AMX), amox = "thisone")
# such as get_column_abx(example_isolates %>% rename(thisone = AMX), amox = "thisone")
dots <- list(...)
if (length(dots) > 0) {
newnames <- suppressWarnings(as.ab(names(dots), info = FALSE))
if (any(is.na(newnames))) {
warning("Invalid antibiotic reference(s): ", toString(names(dots)[is.na(newnames)]),
call. = FALSE, immediate. = TRUE)
warning_("Invalid antibiotic reference(s): ", toString(names(dots)[is.na(newnames)]),
call = FALSE,
immediate = TRUE)
}
# turn all NULLs to NAs
dots <- unlist(lapply(dots, function(x) if (is.null(x)) NA else x))
@@ -176,7 +180,7 @@ get_column_abx <- function(x,
if (length(x) == 0) {
if (info == TRUE) {
message(font_blue("No columns found."))
message_("No columns found.")
}
return(x)
}
@@ -190,24 +194,24 @@ get_column_abx <- function(x,
# succeeded with auto-guessing
if (info == TRUE) {
message(font_blue("OK."))
message_(" OK.", add_fn = list(font_green, font_bold), as_note = FALSE)
}
for (i in seq_len(length(x))) {
if (info == TRUE & verbose == TRUE & !names(x[i]) %in% names(duplicates)) {
message(font_blue(paste0("NOTE: Using column `", font_bold(x[i]), "` as input for `", names(x)[i],
"` (", ab_name(names(x)[i], tolower = TRUE, language = NULL), ").")))
message_("Using column '", font_bold(x[i]), "' as input for ", names(x)[i],
" (", ab_name(names(x)[i], tolower = TRUE, language = NULL), ").")
}
if (info == TRUE & names(x[i]) %in% names(duplicates)) {
warning(font_red(paste0("Using column `", font_bold(x[i]), "` as input for `", names(x)[i],
"` (", ab_name(names(x)[i], tolower = TRUE, language = NULL),
"), although it was matched for multiple antibiotics or columns.")),
call. = FALSE,
immediate. = verbose)
warning_(paste0("Using column '", font_bold(x[i]), "' as input for ", names(x)[i],
" (", ab_name(names(x)[i], tolower = TRUE, language = NULL),
"), although it was matched for multiple antibiotics or columns."),
add_fn = font_red,
call = FALSE,
immediate = verbose)
}
}
if (!is.null(hard_dependencies)) {
hard_dependencies <- unique(hard_dependencies)
if (!all(hard_dependencies %in% names(x))) {
@@ -222,16 +226,11 @@ get_column_abx <- function(x,
if (info == TRUE & !all(soft_dependencies %in% names(x))) {
# missing a soft dependency may lower the reliability
missing <- soft_dependencies[!soft_dependencies %in% names(x)]
missing_msg <- paste(paste0(ab_name(missing, tolower = TRUE, language = NULL),
" (", missing, ")"),
collapse = ", ")
missing_msg <- paste("NOTE: Reliability would be improved if these antimicrobial results would be available too:",
missing_msg)
wrapped <- strwrap(missing_msg,
width = 0.95 * getOption("width"),
exdent = 6)
wrapped <- gsub("\\((.*?)\\)", paste0("(", font_bold("\\1"), ")"), wrapped) # add bold abbreviations
message(font_blue(wrapped, collapse = "\n"))
missing_msg <- vector_and(paste0(ab_name(missing, tolower = TRUE, language = NULL),
" (", font_bold(missing, collapse = NULL), ")"),
quotes = FALSE)
message_("Reliability would be improved if these antimicrobial results would be available too: ",
missing_msg)
}
}
x
@@ -244,8 +243,8 @@ generate_warning_abs_missing <- function(missing, any = FALSE) {
} else {
any_txt <- c("", "are")
}
warning(paste0("Introducing NAs since", any_txt[1], " these antimicrobials ", any_txt[2], " required: ",
paste(missing, collapse = ", ")),
immediate. = TRUE,
call. = FALSE)
warning_(paste0("Introducing NAs since", any_txt[1], " these antimicrobials ", any_txt[2], " required: ",
vector_and(missing, quotes = FALSE)),
immediate = TRUE,
call = FALSE)
}
+203
View File
@@ -0,0 +1,203 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
# GNU General Public License version 2.0 (GNU GPL-2), as published by #
# the Free Software Foundation. #
# We created this package for both routine data analysis and academic #
# research and it was publicly released in the hope that it will be #
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Create Identifier of an Isolate
#'
#' This function will paste the microorganism code with all antimicrobial results into one string for each row in a data set. This is useful to compare isolates, e.g. between institutions or regions, when there is no genotyping available.
#' @inheritSection lifecycle Experimental Lifecycle
#' @inheritParams eucast_rules
#' @param cols_ab a character vector of column names of `x`, or (a combination with) an [antibiotic selector function]([ab_class()]), such as [carbapenems()] and [aminoglycosides()]
#' @rdname isolate_identifier
#' @export
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # automatic selection of microorganism and antibiotics (i.e., all <rsi> columns, see ?as.rsi)
#' x <- isolate_identifier(example_isolates)
#'
#' # ignore microorganism codes, only use antimicrobial results
#' x <- isolate_identifier(example_isolates, col_mo = FALSE, cols_ab = c("AMX", "TZP", "GEN", "TOB"))
#'
#' # select antibiotics from certain antibiotic classes
#' x <- isolate_identifier(example_isolates, cols_ab = c(carbapenems(), aminoglycosides()))
isolate_identifier <- function(x, col_mo = NULL, cols_ab = NULL) {
if (is.null(col_mo)) {
col_mo <- search_type_in_df(x, "mo")
if (is.null(col_mo)) {
# no column found, then ignore the argument
col_mo <- FALSE
}
}
if (isFALSE(col_mo)) {
# is FALSE then ignore mo column
x$col_mo <- ""
col_mo <- "col_mo"
} else if (!is.null(col_mo)) {
x[, col_mo] <- paste0(as.mo(x[, col_mo, drop = TRUE]), "|")
}
cols_ab <- deparse(substitute(cols_ab)) # support ab class selectors: isolate_identifier(x, cols_ab = carbapenems())
if (identical(cols_ab, "NULL")) {
cols_ab <- colnames(x)[vapply(FUN.VALUE = logical(1), x, is.rsi)]
} else {
cols_ab <- tryCatch(colnames(x[, eval(parse(text = cols_ab), envir = parent.frame())]),
# tryCatch adds 4 calls, so total is -5
error = function(e) stop_(e$message, call = -5))
}
# cope with empty values
if (length(cols_ab) == 0 && all(x[, col_mo, drop = TRUE] == "", na.rm = TRUE)) {
warning_("in isolate_identifier(): no column with microorganisms and no columns with antimicrobial agents found", call = FALSE)
} else if (length(cols_ab) == 0) {
warning_("in isolate_identifier(): no columns with antimicrobial agents found", call = FALSE)
}
out <- x[, c(col_mo, cols_ab), drop = FALSE]
out <- do.call(paste, c(out, sep = ""))
out <- gsub("NA", ".", out, fixed = TRUE)
out <- set_clean_class(out, new_class = c("isolate_identifier", "character"))
attr(out, "ab") <- cols_ab
out
}
#' @method all.equal isolate_identifier
#' @inheritParams base::all.equal
#' @param ignore_empty_results a logical to indicate whether empty results must be ignored, so that only values R, S and I will be compared
#' @rdname isolate_identifier
#' @export
all.equal.isolate_identifier <- function(target, current, ignore_empty_results = TRUE, ...) {
meet_criteria(target, allow_class = "isolate_identifier")
meet_criteria(current, allow_class = "isolate_identifier")
meet_criteria(ignore_empty_results, allow_class = "logical", has_length = 1)
if (isTRUE(all.equal.character(target, current))) {
return(TRUE)
}
# vectorise over both target and current
if (length(target) > 1 && length(current) == 1) {
current <- rep(current, length(target))
} else if (length(current) > 1 && length(target) == 1) {
target <- rep(target, length(current))
}
stop_if(length(target) != length(current),
"length of `target` and `current` must be the same, or one must be 1")
get_vector <- function(x) {
if (grepl("|", x, fixed = TRUE)) {
mo <- gsub("(.*)\\|.*", "\\1", x)
} else {
mo <- NULL
}
if (grepl("|", x, fixed = TRUE)) {
ab <- gsub(".*\\|(.*)", "\\1", x)
} else {
ab <- x
}
ab <- strsplit(ab, "")[[1L]]
if (is.null(mo)) {
out <- as.character(ab)
names(out) <- attributes(x)$ab
} else {
out <- as.character(c(mo, ab))
names(out) <- c("mo", attributes(x)$ab)
}
out
}
# run it
for (i in seq_len(length(target))) {
if (i == 1) {
df <- data.frame(object = paste0(c("target[", "current["), i, "]"))
}
trgt <- get_vector(target[i])
crnt <- get_vector(current[i])
if (ignore_empty_results == TRUE) {
diff <- names(trgt[trgt != crnt & trgt != "." & crnt != "."])
} else {
diff <- names(trgt[trgt != crnt])
}
}
stop("THIS FUNCTION IS WORK IN PROGRESS AND NOT AVAILABLE IN THIS BETA VERSION")
}
#' @method print isolate_identifier
#' @export
#' @noRd
print.isolate_identifier <- function(x, ...) {
print(as.character(x), ...)
}
#' @method [ isolate_identifier
#' @export
#' @noRd
"[.isolate_identifier" <- function(x, ...) {
y <- NextMethod()
attributes(y) <- attributes(x)
y
}
#' @method [[ isolate_identifier
#' @export
#' @noRd
"[[.isolate_identifier" <- function(x, ...) {
y <- NextMethod()
attributes(y) <- attributes(x)
y
}
#' @method [<- isolate_identifier
#' @export
#' @noRd
"[<-.isolate_identifier" <- function(i, j, ..., value) {
y <- NextMethod()
attributes(y) <- attributes(i)
y
}
#' @method [[<- isolate_identifier
#' @export
#' @noRd
"[[<-.isolate_identifier" <- function(i, j, ..., value) {
y <- NextMethod()
attributes(y) <- attributes(i)
y
}
#' @method c isolate_identifier
#' @export
#' @noRd
c.isolate_identifier <- function(x, ...) {
y <- NextMethod()
attributes(y) <- attributes(x)
y
}
#' @method unique isolate_identifier
#' @export
#' @noRd
unique.isolate_identifier <- function(x, incomparables = FALSE, ...) {
y <- NextMethod()
attributes(y) <- attributes(x)
y
}
+45 -19
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,24 +20,24 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Join [microorganisms] to a data set
#' Join [microorganisms] to a Data Set
#'
#' Join the data set [microorganisms] easily to an existing table or character vector.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @rdname join
#' @name join
#' @aliases join inner_join
#' @param x existing table to join, or character vector
#' @param by a variable to join by - if left empty will search for a column with class [`mo`] (created with [as.mo()]) or will be `"mo"` if that column name exists in `x`, could otherwise be a column name of `x` with values that exist in `microorganisms$mo` (like `by = "bacteria_id"`), or another column in [microorganisms] (but then it should be named, like `by = c("bacteria_id" = "fullname")`)
#' @param by a variable to join by - if left empty will search for a column with class [`mo`] (created with [as.mo()]) or will be `"mo"` if that column name exists in `x`, could otherwise be a column name of `x` with values that exist in `microorganisms$mo` (such as `by = "bacteria_id"`), or another column in [microorganisms] (but then it should be named, like `by = c("bacteria_id" = "fullname")`)
#' @param suffix if there are non-joined duplicate variables in `x` and `y`, these suffixes will be added to the output to disambiguate them. Should be a character vector of length 2.
#' @param ... ignored
#' @details **Note:** As opposed to the `join()` functions of `dplyr`, [character] vectors are supported and at default existing columns will get a suffix `"2"` and the newly joined columns will not get a suffix.
#'
#' If the `dplyr` package is installed, their join functions will be used. Otherwise, the much slower [merge()] function from base R will be used.
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @export
#' @examples
#' left_join_microorganisms(as.mo("K. pneumoniae"))
@@ -61,8 +61,12 @@
#' }
#' }
inner_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
meet_criteria(x, allow_class = c("data.frame", "character"))
meet_criteria(by, allow_class = "character", allow_NULL = TRUE)
meet_criteria(suffix, allow_class = "character", has_length = 2)
check_dataset_integrity()
check_groups_before_join(x, "inner_join_microorganisms")
x <- check_groups_before_join(x, "inner_join_microorganisms")
checked <- joins_check_df(x, by)
x_class <- get_prejoined_class(x)
x <- checked$x
@@ -79,7 +83,7 @@ inner_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
)
}
if (NROW(join) > NROW(x)) {
warning("The newly joined tbl contains ", nrow(join) - nrow(x), " rows more that its original.")
warning_("The newly joined tbl contains ", nrow(join) - nrow(x), " rows more that its original.")
}
class(join) <- x_class
join
@@ -88,8 +92,12 @@ inner_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
#' @rdname join
#' @export
left_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
meet_criteria(x, allow_class = c("data.frame", "character"))
meet_criteria(by, allow_class = "character", allow_NULL = TRUE)
meet_criteria(suffix, allow_class = "character", has_length = 2)
check_dataset_integrity()
check_groups_before_join(x, "left_join_microorganisms")
x <- check_groups_before_join(x, "left_join_microorganisms")
checked <- joins_check_df(x, by)
x_class <- get_prejoined_class(x)
x <- checked$x
@@ -106,7 +114,7 @@ left_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
)
}
if (NROW(join) > NROW(x)) {
warning("The newly joined tbl contains ", nrow(join) - nrow(x), " rows more that its original.")
warning_("The newly joined tbl contains ", nrow(join) - nrow(x), " rows more that its original.")
}
class(join) <- x_class
join
@@ -115,8 +123,12 @@ left_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
#' @rdname join
#' @export
right_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
meet_criteria(x, allow_class = c("data.frame", "character"))
meet_criteria(by, allow_class = "character", allow_NULL = TRUE)
meet_criteria(suffix, allow_class = "character", has_length = 2)
check_dataset_integrity()
check_groups_before_join(x, "right_join_microorganisms")
x <- check_groups_before_join(x, "right_join_microorganisms")
checked <- joins_check_df(x, by)
x_class <- get_prejoined_class(x)
x <- checked$x
@@ -133,7 +145,7 @@ right_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
)
}
if (NROW(join) > NROW(x)) {
warning("The newly joined tbl contains ", nrow(join) - nrow(x), " rows more that its original.")
warning_("The newly joined tbl contains ", nrow(join) - nrow(x), " rows more that its original.")
}
class(join) <- x_class
join
@@ -142,8 +154,12 @@ right_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
#' @rdname join
#' @export
full_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
meet_criteria(x, allow_class = c("data.frame", "character"))
meet_criteria(by, allow_class = "character", allow_NULL = TRUE)
meet_criteria(suffix, allow_class = "character", has_length = 2)
check_dataset_integrity()
check_groups_before_join(x, "full_join_microorganisms")
x <- check_groups_before_join(x, "full_join_microorganisms")
checked <- joins_check_df(x, by)
x_class <- get_prejoined_class(x)
x <- checked$x
@@ -160,7 +176,7 @@ full_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
)
}
if (NROW(join) > NROW(x)) {
warning("The newly joined tbl contains ", nrow(join) - nrow(x), " rows more that its original.")
warning_("The newly joined tbl contains ", nrow(join) - nrow(x), " rows more that its original.")
}
class(join) <- x_class
join
@@ -169,8 +185,11 @@ full_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) {
#' @rdname join
#' @export
semi_join_microorganisms <- function(x, by = NULL, ...) {
meet_criteria(x, allow_class = c("data.frame", "character"))
meet_criteria(by, allow_class = "character", allow_NULL = TRUE)
check_dataset_integrity()
check_groups_before_join(x, "semi_join_microorganisms")
x <- check_groups_before_join(x, "semi_join_microorganisms")
x_class <- get_prejoined_class(x)
checked <- joins_check_df(x, by)
x <- checked$x
@@ -193,8 +212,11 @@ semi_join_microorganisms <- function(x, by = NULL, ...) {
#' @rdname join
#' @export
anti_join_microorganisms <- function(x, by = NULL, ...) {
meet_criteria(x, allow_class = c("data.frame", "character"))
meet_criteria(by, allow_class = "character", allow_NULL = TRUE)
check_dataset_integrity()
check_groups_before_join(x, "anti_join_microorganisms")
x <- check_groups_before_join(x, "anti_join_microorganisms")
checked <- joins_check_df(x, by)
x_class <- get_prejoined_class(x)
x <- checked$x
@@ -233,7 +255,7 @@ joins_check_df <- function(x, by) {
stop("Cannot join - no column found with name 'mo' or with class <mo>.", call. = FALSE)
}
}
message('Joining, by = "', by, '"') # message same as dplyr::join functions
message_('Joining, by = "', by, '"', add_fn = font_black, as_note = FALSE) # message same as dplyr::join functions
}
if (is.null(names(by))) {
joinby <- colnames(microorganisms)[1]
@@ -255,6 +277,10 @@ get_prejoined_class <- function(x) {
check_groups_before_join <- function(x, fn) {
if (is.data.frame(x) && !is.null(attributes(x)$groups)) {
warning("Groups are dropped, since the ", fn, "() function relies on merge() from base R, not on join() from dplyr.", call. = FALSE)
x <- pm_ungroup(x)
attr(x, "groups") <- NULL
class(x) <- class(x)[!class(x) %like% "group"]
warning_("Groups are dropped, since the ", fn, "() function relies on merge() from base R.", call = FALSE)
}
x
}
+82 -41
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,22 +20,25 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Key antibiotics for first *weighted* isolates
#' Key Antibiotics for First (Weighted) Isolates
#'
#' These function can be used to determine first isolates (see [first_isolate()]). Using key antibiotics to determine first isolates is more reliable than without key antibiotics. These selected isolates will then be called first *weighted* isolates.
#' @inheritSection lifecycle Stable lifecycle
#' @param x table with antibiotics coloms, like `AMX` or `amox`
#' @param y,z characters to compare
#' These function can be used to determine first isolates (see [first_isolate()]). Using key antibiotics to determine first isolates is more reliable than without key antibiotics. These selected isolates can then be called first 'weighted' isolates.
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a [data.frame] with antibiotics columns, like `AMX` or `amox`. Can be left blank to determine automatically
#' @param y,z character vectors to compare
#' @inheritParams first_isolate
#' @param universal_1,universal_2,universal_3,universal_4,universal_5,universal_6 column names of **broad-spectrum** antibiotics, case-insensitive. At default, the columns containing these antibiotics will be guessed with [guess_ab_col()].
#' @param GramPos_1,GramPos_2,GramPos_3,GramPos_4,GramPos_5,GramPos_6 column names of antibiotics for **Gram-positives**, case-insensitive. At default, the columns containing these antibiotics will be guessed with [guess_ab_col()].
#' @param GramNeg_1,GramNeg_2,GramNeg_3,GramNeg_4,GramNeg_5,GramNeg_6 column names of antibiotics for **Gram-negatives**, case-insensitive. At default, the columns containing these antibiotics will be guessed with [guess_ab_col()].
#' @param warnings give warning about missing antibiotic columns, they will anyway be ignored
#' @param ... other parameters passed on to function
#' @details The function [key_antibiotics()] returns a character vector with 12 antibiotic results for every isolate. These isolates can then be compared using [key_antibiotics_equal()], to check if two isolates have generally the same antibiogram. Missing and invalid values are replaced with a dot (`"."`) by [key_antibiotics()] and ignored by [key_antibiotics_equal()].
#' @param universal_1,universal_2,universal_3,universal_4,universal_5,universal_6 column names of **broad-spectrum** antibiotics, case-insensitive. See details for which antibiotics will be used at default (which are guessed with [guess_ab_col()]).
#' @param GramPos_1,GramPos_2,GramPos_3,GramPos_4,GramPos_5,GramPos_6 column names of antibiotics for **Gram-positives**, case-insensitive. See details for which antibiotics will be used at default (which are guessed with [guess_ab_col()]).
#' @param GramNeg_1,GramNeg_2,GramNeg_3,GramNeg_4,GramNeg_5,GramNeg_6 column names of antibiotics for **Gram-negatives**, case-insensitive. See details for which antibiotics will be used at default (which are guessed with [guess_ab_col()]).
#' @param warnings give a warning about missing antibiotic columns (they will be ignored)
#' @param ... other arguments passed on to functions
#' @details
#' The [key_antibiotics()] function is context-aware. This means that then the `x` argument can be left blank, see *Examples*.
#'
#' The function [key_antibiotics()] returns a character vector with 12 antibiotic results for every isolate. These isolates can then be compared using [key_antibiotics_equal()], to check if two isolates have generally the same antibiogram. Missing and invalid values are replaced with a dot (`"."`) by [key_antibiotics()] and ignored by [key_antibiotics_equal()].
#'
#' The [first_isolate()] function only uses this function on the same microbial species from the same patient. Using this, e.g. an MRSA will be included after a susceptible *S. aureus* (MSSA) is found within the same patient episode. Without key antibiotic comparison it would not. See [first_isolate()] for more info.
#'
@@ -68,44 +71,44 @@
#' - Meropenem
#'
#' The function [key_antibiotics_equal()] checks the characters returned by [key_antibiotics()] for equality, and returns a [`logical`] vector.
#' @inheritSection first_isolate Key antibiotics
#' @inheritSection first_isolate Key Antibiotics
#' @rdname key_antibiotics
#' @export
#' @seealso [first_isolate()]
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # `example_isolates` is a dataset available in the AMR package.
#' # `example_isolates` is a data set available in the AMR package.
#' # See ?example_isolates.
#'
#' # output of the `key_antibiotics` function could be like this:
#' # output of the `key_antibiotics()` function could be like this:
#' strainA <- "SSSRR.S.R..S"
#' strainB <- "SSSIRSSSRSSS"
#'
#' # can those strings can be compared with:
#' # those strings can be compared with:
#' key_antibiotics_equal(strainA, strainB)
#' # TRUE, because I is ignored (as well as missing values)
#'
#' key_antibiotics_equal(strainA, strainB, ignore_I = FALSE)
#' # FALSE, because I is not ignored and so the 4th value differs
#' # FALSE, because I is not ignored and so the 4th character differs
#'
#' \donttest{
#' if (require("dplyr")) {
#' # set key antibiotics to a new variable
#' my_patients <- example_isolates %>%
#' mutate(keyab = key_antibiotics(.)) %>%
#' mutate(keyab = key_antibiotics()) %>% # no need to define `x`
#' mutate(
#' # now calculate first isolates
#' first_regular = first_isolate(., col_keyantibiotics = FALSE),
#' first_regular = first_isolate(col_keyantibiotics = FALSE),
#' # and first WEIGHTED isolates
#' first_weighted = first_isolate(., col_keyantibiotics = "keyab")
#' first_weighted = first_isolate(col_keyantibiotics = "keyab")
#' )
#'
#' # Check the difference, in this data set it results in 7% more isolates:
#' # Check the difference, in this data set it results in a lot more isolates:
#' sum(my_patients$first_regular, na.rm = TRUE)
#' sum(my_patients$first_weighted, na.rm = TRUE)
#' }
#' }
key_antibiotics <- function(x,
key_antibiotics <- function(x = NULL,
col_mo = NULL,
universal_1 = guess_ab_col(x, "amoxicillin"),
universal_2 = guess_ab_col(x, "amoxicillin/clavulanic acid"),
@@ -127,11 +130,40 @@ key_antibiotics <- function(x,
GramNeg_6 = guess_ab_col(x, "meropenem"),
warnings = TRUE,
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
x <- tryCatch(get_current_data(arg_name = "x", call = -2), error = function(e) x)
}
meet_criteria(x, allow_class = "data.frame") # also checks dimensions to be >0
meet_criteria(col_mo, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_1, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_2, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_3, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_4, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_5, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(universal_6, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_1, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_2, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_3, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_4, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_5, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramPos_6, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_1, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_2, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_3, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_4, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_5, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(GramNeg_6, allow_class = "character", has_length = 1, allow_NULL = TRUE, allow_NA = TRUE)
meet_criteria(warnings, allow_class = "logical", has_length = 1)
# force regular data.frame, not a tibble or data.table
x <- as.data.frame(x, stringsAsFactors = FALSE)
dots <- unlist(list(...))
if (length(dots) != 0) {
# backwards compatibility with old parameters
dots.names <- dots %pm>% names()
# backwards compatibility with old arguments
dots.names <- names(dots)
if ("info" %in% dots.names) {
warnings <- dots[which(dots.names == "info")]
}
@@ -141,8 +173,10 @@ key_antibiotics <- function(x,
# -- mo
if (is.null(col_mo)) {
col_mo <- search_type_in_df(x = x, type = "mo")
stop_if(is.null(col_mo), "`col_mo` must be set")
} else {
stop_ifnot(col_mo %in% colnames(x), "column '", col_mo, "' (`col_mo`) not found")
}
stop_if(is.null(col_mo), "`col_mo` must be set")
# check columns
col.list <- c(universal_1, universal_2, universal_3, universal_4, universal_5, universal_6,
@@ -167,11 +201,11 @@ key_antibiotics <- function(x,
}
if (!all(col.list %in% colnames(x))) {
if (warnings == TRUE) {
warning("Some columns do not exist and will be ignored: ",
col.list.bak[!(col.list %in% colnames(x))] %pm>% toString(),
".\nTHIS MAY STRONGLY INFLUENCE THE OUTCOME.",
immediate. = TRUE,
call. = FALSE)
warning_("Some columns do not exist and will be ignored: ",
col.list.bak[!(col.list %in% colnames(x))] %pm>% toString(),
".\nTHIS MAY STRONGLY INFLUENCE THE OUTCOME.",
immediate = TRUE,
call = FALSE)
}
}
col.list
@@ -205,8 +239,9 @@ key_antibiotics <- function(x,
GramPos_4, GramPos_5, GramPos_6)
gram_positive <- gram_positive[!is.null(gram_positive)]
gram_positive <- gram_positive[!is.na(gram_positive)]
if (length(gram_positive) < 12) {
warning("only using ", length(gram_positive), " different antibiotics as key antibiotics for Gram-positives. See ?key_antibiotics.", call. = FALSE)
if (length(gram_positive) < 12 & message_not_thrown_before("key_antibiotics.grampos")) {
warning_("Only using ", length(gram_positive), " different antibiotics as key antibiotics for Gram-positives. See ?key_antibiotics.", call = FALSE)
remember_thrown_message("key_antibiotics.grampos")
}
gram_negative <- c(universal,
@@ -214,11 +249,11 @@ key_antibiotics <- function(x,
GramNeg_4, GramNeg_5, GramNeg_6)
gram_negative <- gram_negative[!is.null(gram_negative)]
gram_negative <- gram_negative[!is.na(gram_negative)]
if (length(gram_negative) < 12) {
warning("only using ", length(gram_negative), " different antibiotics as key antibiotics for Gram-negatives. See ?key_antibiotics.", call. = FALSE)
if (length(gram_negative) < 12 & message_not_thrown_before("key_antibiotics.gramneg")) {
warning_("Only using ", length(gram_negative), " different antibiotics as key antibiotics for Gram-negatives. See ?key_antibiotics.", call = FALSE)
remember_thrown_message("key_antibiotics.gramneg")
}
x <- as.data.frame(x, stringsAsFactors = FALSE)
x[, col_mo] <- as.mo(x[, col_mo, drop = TRUE])
x$gramstain <- mo_gramstain(x[, col_mo, drop = TRUE], language = NULL)
x$key_ab <- NA_character_
@@ -243,7 +278,7 @@ key_antibiotics <- function(x,
key_abs <- toupper(gsub("[^SIR]", ".", gsub("(NA|NULL)", ".", x$key_ab)))
if (pm_n_distinct(key_abs) == 1) {
warning("No distinct key antibiotics determined.", call. = FALSE)
warning_("No distinct key antibiotics determined.", call = FALSE)
}
key_abs
@@ -258,14 +293,20 @@ key_antibiotics_equal <- function(y,
ignore_I = TRUE,
points_threshold = 2,
info = FALSE) {
meet_criteria(y, allow_class = "character")
meet_criteria(z, allow_class = "character")
meet_criteria(type, allow_class = "character", has_length = c(1, 2))
meet_criteria(ignore_I, allow_class = "logical", has_length = 1)
meet_criteria(points_threshold, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(info, allow_class = "logical", has_length = 1)
stop_ifnot(length(y) == length(z), "length of `y` and `z` must be equal")
# y is active row, z is lag
x <- y
y <- z
type <- type[1]
stop_ifnot(length(x) == length(y), "length of `x` and `y` must be equal")
# only show progress bar on points or when at least 5000 isolates
info_needed <- info == TRUE & (type == "points" | length(x) > 5000)
+15 -7
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,21 +20,23 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Kurtosis of the sample
#' Kurtosis of the Sample
#'
#' @description Kurtosis is a measure of the "tailedness" of the probability distribution of a real-valued random variable. A normal distribution has a kurtosis of 3 and a excess kurtosis of 0.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a vector of values, a [matrix] or a [data.frame]
#' @param na.rm a logical to indicate whether `NA` values should be stripped before the computation proceeds
#' @param excess a logical to indicate whether the *excess kurtosis* should be returned, defined as the kurtosis minus 3.
#' @seealso [skewness()]
#' @rdname kurtosis
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @export
kurtosis <- function(x, na.rm = FALSE, excess = FALSE) {
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
meet_criteria(excess, allow_class = "logical", has_length = 1)
UseMethod("kurtosis")
}
@@ -42,6 +44,8 @@ kurtosis <- function(x, na.rm = FALSE, excess = FALSE) {
#' @rdname kurtosis
#' @export
kurtosis.default <- function(x, na.rm = FALSE, excess = FALSE) {
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
meet_criteria(excess, allow_class = "logical", has_length = 1)
x <- as.vector(x)
if (na.rm == TRUE) {
x <- x[!is.na(x)]
@@ -56,6 +60,8 @@ kurtosis.default <- function(x, na.rm = FALSE, excess = FALSE) {
#' @rdname kurtosis
#' @export
kurtosis.matrix <- function(x, na.rm = FALSE, excess = FALSE) {
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
meet_criteria(excess, allow_class = "logical", has_length = 1)
apply(x, 2, kurtosis.default, na.rm = na.rm, excess = excess)
}
@@ -63,5 +69,7 @@ kurtosis.matrix <- function(x, na.rm = FALSE, excess = FALSE) {
#' @rdname kurtosis
#' @export
kurtosis.data.frame <- function(x, na.rm = FALSE, excess = FALSE) {
sapply(x, kurtosis.default, na.rm = na.rm, excess = excess)
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
meet_criteria(excess, allow_class = "logical", has_length = 1)
vapply(FUN.VALUE = double(1), x, kurtosis.default, na.rm = na.rm, excess = excess)
}
+10 -10
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,35 +20,35 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
###############
# NOTE TO SELF: could also have done this with the 'lifecycle' package, but why add a package dependency for such an easy job??
###############
#' Lifecycles of functions in the `AMR` package
#' Lifecycles of Functions in the `amr` Package
#' @name lifecycle
#' @rdname lifecycle
#' @description Functions in this `AMR` package are categorised using [the lifecycle circle of the Tidyverse as found on www.tidyverse.org/lifecycle](https://www.Tidyverse.org/lifecycle).
#'
#' \if{html}{\figure{lifecycle_tidyverse.svg}{options: height=200px style=margin-bottom:5px} \cr}
#' This page contains a section for every lifecycle (with text borrowed from the aforementioned Tidyverse website), so they can be used in the manual pages of the functions.
#' @section Experimental lifecycle:
#' @section Experimental Lifecycle:
#' \if{html}{\figure{lifecycle_experimental.svg}{options: style=margin-bottom:5px} \cr}
#' The [lifecycle][AMR::lifecycle] of this function is **experimental**. An experimental function is in early stages of development. The unlying code might be changing frequently. Experimental functions might be removed without deprecation, so you are generally best off waiting until a function is more mature before you use it in production code. Experimental functions are only available in development versions of this `AMR` package and will thus not be included in releases that are submitted to CRAN, since such functions have not yet matured enough.
#' @section Maturing lifecycle:
#' @section Maturing Lifecycle:
#' \if{html}{\figure{lifecycle_maturing.svg}{options: style=margin-bottom:5px} \cr}
#' The [lifecycle][AMR::lifecycle] of this function is **maturing**. The unlying code of a maturing function has been roughed out, but finer details might still change. Since this function needs wider usage and more extensive testing, you are very welcome [to suggest changes at our repository](https://github.com/msberends/AMR/issues) or [write us an email (see section 'Contact Us')][AMR::AMR].
#' @section Stable lifecycle:
#' @section Stable Lifecycle:
#' \if{html}{\figure{lifecycle_stable.svg}{options: style=margin-bottom:5px} \cr}
#' The [lifecycle][AMR::lifecycle] of this function is **stable**. In a stable function, major changes are unlikely. This means that the unlying code will generally evolve by adding new arguments; removing arguments or changing the meaning of existing arguments will be avoided.
#'
#' If the unlying code needs breaking changes, they will occur gradually. For example, a parameter will be deprecated and first continue to work, but will emit an message informing you of the change. Next, typically after at least one newly released version on CRAN, the message will be transformed to an error.
#' @section Retired lifecycle:
#' If the unlying code needs breaking changes, they will occur gradually. For example, a argument will be deprecated and first continue to work, but will emit an message informing you of the change. Next, typically after at least one newly released version on CRAN, the message will be transformed to an error.
#' @section Retired Lifecycle:
#' \if{html}{\figure{lifecycle_retired.svg}{options: style=margin-bottom:5px} \cr}
#' The [lifecycle][AMR::lifecycle] of this function is **retired**. A retired function is no longer under active development, and (if appropiate) a better alternative is available. No new arguments will be added, and only the most critical bugs will be fixed. In a future version, this function will be removed.
#' @section Questioning lifecycle:
#' @section Questioning Lifecycle:
#' \if{html}{\figure{lifecycle_questioning.svg}{options: style=margin-bottom:5px} \cr}
#' The [lifecycle][AMR::lifecycle] of this function is **questioning**. This function might be no longer be optimal approach, or is it questionable whether this function should be in this `AMR` package at all.
NULL
+27 -38
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,13 +20,13 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Pattern Matching
#' Pattern Matching with Keyboard Shortcut
#'
#' Convenient wrapper around [grep()] to match a pattern: `x %like% pattern`. It always returns a [`logical`] vector and is always case-insensitive (use `x %like_case% pattern` for case-sensitive matching). Also, `pattern` can be as long as `x` to compare items of each index in both vectors, or they both can have the same length to iterate over all cases.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a character vector where matches are sought, or an object which can be coerced by [as.character()] to a character vector.
#' @param pattern a character string containing a regular expression (or [character] string for `fixed = TRUE`) to be matched in the given character vector. Coerced by [as.character()] to a character string if possible. If a [character] vector of length 2 or more is supplied, the first element is used with a warning.
#' @param ignore.case if `FALSE`, the pattern matching is *case sensitive* and if `TRUE`, case is ignored during matching.
@@ -39,12 +39,12 @@
#' * Is case-insensitive (use `%like_case%` for case-sensitive matching)
#' * Supports multiple patterns
#' * Checks if `pattern` is a regular expression and sets `fixed = TRUE` if not, to greatly improve speed
#' * Tries again with `perl = TRUE` if regex fails
#' * Always uses compatibility with Perl
#'
#' Using RStudio? This function can also be inserted from the Addins menu and can have its own Keyboard Shortcut like `Ctrl+Shift+L` or `Cmd+Shift+L` (see `Tools` > `Modify Keyboard Shortcuts...`).
#' Using RStudio? The text `%like%` can also be directly inserted in your code from the Addins menu and can have its own Keyboard Shortcut like `Ctrl+Shift+L` or `Cmd+Shift+L` (see `Tools` > `Modify Keyboard Shortcuts...`).
#' @source Idea from the [`like` function from the `data.table` package](https://github.com/Rdatatable/data.table/blob/master/R/like.R)
#' @seealso [grep()]
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # simple test
#' a <- "This is a test"
@@ -68,10 +68,14 @@
#' }
#' }
like <- function(x, pattern, ignore.case = TRUE) {
meet_criteria(x, allow_NA = TRUE)
meet_criteria(pattern, allow_NA = FALSE)
meet_criteria(ignore.case, allow_class = "logical", has_length = 1)
# set to fixed if no regex found
fixed <- !any(is_possibly_regex(pattern))
if (ignore.case == TRUE) {
# set here, otherwise if fixed = TRUE, this warning will be thrown: argument 'ignore.case = TRUE' will be ignored
# set here, otherwise if fixed = TRUE, this warning will be thrown: argument `ignore.case = TRUE` will be ignored
x <- tolower(x)
pattern <- tolower(pattern)
}
@@ -79,6 +83,10 @@ like <- function(x, pattern, ignore.case = TRUE) {
if (length(pattern) > 1 & length(x) == 1) {
x <- rep(x, length(pattern))
}
if (all(is.na(x))) {
return(rep(FALSE, length(x)))
}
if (length(pattern) > 1) {
res <- vector(length = length(pattern))
@@ -91,10 +99,10 @@ like <- function(x, pattern, ignore.case = TRUE) {
if (is.factor(x[i])) {
res[i] <- as.integer(x[i]) %in% grep(pattern[i], levels(x[i]), ignore.case = FALSE, fixed = fixed)
} else {
res[i] <- grepl(pattern[i], x[i], ignore.case = FALSE, fixed = fixed)
res[i] <- grepl(pattern[i], x[i], ignore.case = FALSE, fixed = fixed, perl = !fixed)
}
}
res <- sapply(pattern, function(pttrn) grepl(pttrn, x, ignore.case = FALSE, fixed = fixed))
res <- vapply(FUN.VALUE = logical(1), pattern, function(pttrn) grepl(pttrn, x, ignore.case = FALSE, fixed = fixed))
res2 <- as.logical(rowSums(res))
# get only first item of every hit in pattern
res2[duplicated(res)] <- FALSE
@@ -104,9 +112,9 @@ like <- function(x, pattern, ignore.case = TRUE) {
# x and pattern are of same length, so items with each other
for (i in seq_len(length(res))) {
if (is.factor(x[i])) {
res[i] <- as.integer(x[i]) %in% grep(pattern[i], levels(x[i]), ignore.case = FALSE, fixed = fixed)
res[i] <- as.integer(x[i]) %in% grep(pattern[i], levels(x[i]), ignore.case = FALSE, fixed = fixed, perl = !fixed)
} else {
res[i] <- grepl(pattern[i], x[i], ignore.case = FALSE, fixed = fixed)
res[i] <- grepl(pattern[i], x[i], ignore.case = FALSE, fixed = fixed, perl = !fixed)
}
}
return(res)
@@ -115,43 +123,24 @@ like <- function(x, pattern, ignore.case = TRUE) {
# the regular way how grepl works; just one pattern against one or more x
if (is.factor(x)) {
as.integer(x) %in% grep(pattern, levels(x), ignore.case = FALSE, fixed = fixed)
as.integer(x) %in% grep(pattern, levels(x), ignore.case = FALSE, fixed = fixed, perl = !fixed)
} else {
tryCatch(grepl(pattern, x, ignore.case = FALSE, fixed = fixed),
error = function(e) {
if (grepl("invalid reg(ular )?exp", e$message, ignore.case = TRUE)) {
# try with perl = TRUE:
return(grepl(pattern = pattern,
x = x,
ignore.case = FALSE,
fixed = fixed,
perl = TRUE))
} else {
# stop otherwise
stop(e$message)
}
})
grepl(pattern, x, ignore.case = FALSE, fixed = fixed, perl = !fixed)
}
}
#' @rdname like
#' @export
"%like%" <- function(x, pattern) {
meet_criteria(x, allow_NA = TRUE)
meet_criteria(pattern, allow_NA = FALSE)
like(x, pattern, ignore.case = TRUE)
}
#' @rdname like
#' @export
"%like_case%" <- function(x, pattern) {
meet_criteria(x, allow_NA = TRUE)
meet_criteria(pattern, allow_NA = FALSE)
like(x, pattern, ignore.case = FALSE)
}
# don't export his one, it's just for convenience in eucast_rules()
# match all Klebsiella and Raoultella, but not K. aerogenes: fullname %like_perl% "^(Klebsiella(?! aerogenes)|Raoultella)"
"%like_perl%" <- function(x, pattern) {
grepl(x = tolower(x),
pattern = tolower(pattern),
perl = TRUE,
fixed = FALSE,
ignore.case = TRUE)
}
+478 -144
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,40 +20,95 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Determine multidrug-resistant organisms (MDRO)
#' Determine Multidrug-Resistant Organisms (MDRO)
#'
#' Determine which isolates are multidrug-resistant organisms (MDRO) according to international and national guidelines.
#' @inheritSection lifecycle Stable lifecycle
#' @param guideline a specific guideline to follow. When left empty, the publication by Magiorakos *et al.* (2012, Clinical Microbiology and Infection) will be followed, please see *Details*.
#' Determine which isolates are multidrug-resistant organisms (MDRO) according to international, national and custom guidelines.
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a [data.frame] with antibiotics columns, like `AMX` or `amox`. Can be left blank for automatic determination.
#' @param guideline a specific guideline to follow, see sections *Supported international / national guidelines* and *Using Custom Guidelines* below. When left empty, the publication by Magiorakos *et al.* (see below) will be followed.
#' @param ... in case of [custom_mdro_guideline()]: a set of rules, see section *Using Custom Guidelines* below. Otherwise: column name of an antibiotic, see section *Antibiotics* below.
#' @param as_factor a [logical] to indicate whether the returned value should be an ordered [factor] (`TRUE`, default), or otherwise a [character] vector
#' @inheritParams eucast_rules
#' @param pct_required_classes minimal required percentage of antimicrobial classes that must be available per isolate, rounded down. For example, with the default guideline, 17 antimicrobial classes must be available for *S. aureus*. Setting this `pct_required_classes` argument to `0.5` (default) means that for every *S. aureus* isolate at least 8 different classes must be available. Any lower number of available classes will return `NA` for that isolate.
#' @param combine_SI a [logical] to indicate whether all values of S and I must be merged into one, so resistance is only considered when isolates are R, not I. As this is the default behaviour of the [mdro()] function, it follows the redefinition by EUCAST about the interpretation of I (increased exposure) in 2019, see section 'Interpretation of S, I and R' below. When using `combine_SI = FALSE`, resistance is considered when isolates are R or I.
#' @param verbose a logical to turn Verbose mode on and off (default is off). In Verbose mode, the function does not return the MDRO results, but instead returns a data set in logbook form with extensive info about which isolates would be MDRO-positive, or why they are not.
#' @inheritSection eucast_rules Antibiotics
#' @details
#' These functions are context-aware. This means that then the `x` argument can be left blank, see *Examples*.
#'
#' For the `pct_required_classes` argument, values above 1 will be divided by 100. This is to support both fractions (`0.75` or `3/4`) and percentages (`75`).
#'
#' **Note:** Every test that involves the Enterobacteriaceae family, will internally be performed using its newly named *order* Enterobacterales, since the Enterobacteriaceae family has been taxonomically reclassified by Adeolu *et al.* in 2016. Before that, Enterobacteriaceae was the only family under the Enterobacteriales (with an i) order. All species under the old Enterobacteriaceae family are still under the new Enterobacterales (without an i) order, but divided into multiple families. The way tests are performed now by this [mdro()] function makes sure that results from before 2016 and after 2016 are identical.
#'
#' @section Supported International / National Guidelines:
#'
#' Currently supported guidelines are (case-insensitive):
#'
#' - `guideline = "CMI2012"`\cr
#' Magiorakos AP, Srinivasan A *et al.* "Multidrug-resistant, extensively drug-resistant and pandrug-resistant bacteria: an international expert proposal for interim standard definitions for acquired resistance." Clinical Microbiology and Infection (2012) ([link](https://www.clinicalmicrobiologyandinfection.com/article/S1198-743X(14)61632-3/fulltext))
#' - `guideline = "EUCAST3.2"` (or simply `guideline = "EUCAST"`)\cr
#' The European international guideline - EUCAST Expert Rules Version 3.2 "Intrinsic Resistance and Unusual Phenotypes" ([link](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/2020/Intrinsic_Resistance_and_Unusual_Phenotypes_Tables_v3.2_20200225.pdf))
#' - `guideline = "EUCAST3.1"`\cr
#' The European international guideline - EUCAST Expert Rules Version 3.1 "Intrinsic Resistance and Exceptional Phenotypes Tables" ([link](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/Expert_rules_intrinsic_exceptional_V3.1.pdf))
#' - `guideline = "TB"`\cr
#' The international guideline for multi-drug resistant tuberculosis - World Health Organization "Companion handbook to the WHO guidelines for the programmatic management of drug-resistant tuberculosis" ([link](https://www.who.int/tb/publications/pmdt_companionhandbook/en/))
#' - `guideline = "MRGN"`\cr
#' The German national guideline - Mueller et al. (2015) Antimicrobial Resistance and Infection Control 4:7. DOI: 10.1186/s13756-015-0047-6
#' - `guideline = "BRMO"`\cr
#' The Dutch national guideline - Rijksinstituut voor Volksgezondheid en Milieu "WIP-richtlijn BRMO (Bijzonder Resistente Micro-Organismen) (ZKH)" ([link](https://www.rivm.nl/wip-richtlijn-brmo-bijzonder-resistente-micro-organismen-zkh))
#' * `guideline = "CMI2012"` (default)
#'
#' Magiorakos AP, Srinivasan A *et al.* "Multidrug-resistant, extensively drug-resistant and pandrug-resistant bacteria: an international expert proposal for interim standard definitions for acquired resistance." Clinical Microbiology and Infection (2012) ([link](https://www.clinicalmicrobiologyandinfection.com/article/S1198-743X(14)61632-3/fulltext))
#'
#' * `guideline = "EUCAST3.2"` (or simply `guideline = "EUCAST"`)
#'
#' The European international guideline - EUCAST Expert Rules Version 3.2 "Intrinsic Resistance and Unusual Phenotypes" ([link](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/2020/Intrinsic_Resistance_and_Unusual_Phenotypes_Tables_v3.2_20200225.pdf))
#'
#' * `guideline = "EUCAST3.1"`
#'
#' The European international guideline - EUCAST Expert Rules Version 3.1 "Intrinsic Resistance and Exceptional Phenotypes Tables" ([link](https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/Expert_rules_intrinsic_exceptional_V3.1.pdf))
#'
#' * `guideline = "TB"`
#'
#' The international guideline for multi-drug resistant tuberculosis - World Health Organization "Companion handbook to the WHO guidelines for the programmatic management of drug-resistant tuberculosis" ([link](https://www.who.int/tb/publications/pmdt_companionhandbook/en/))
#'
#' * `guideline = "MRGN"`
#'
#' The German national guideline - Mueller et al. (2015) Antimicrobial Resistance and Infection Control 4:7; \doi{10.1186/s13756-015-0047-6}
#'
#' * `guideline = "BRMO"`
#'
#' The Dutch national guideline - Rijksinstituut voor Volksgezondheid en Milieu "WIP-richtlijn BRMO (Bijzonder Resistente Micro-Organismen) (ZKH)" ([link](https://www.rivm.nl/wip-richtlijn-brmo-bijzonder-resistente-micro-organismen-zkh))
#'
#' Please suggest your own (country-specific) guidelines by letting us know: <https://github.com/msberends/AMR/issues/new>.
#'
#' **Note:** Every test that involves the Enterobacteriaceae family, will internally be performed using its newly named *order* Enterobacterales, since the Enterobacteriaceae family has been taxonomically reclassified by Adeolu *et al.* in 2016. Before that, Enterobacteriaceae was the only family under the Enterobacteriales (with an i) order. All species under the old Enterobacteriaceae family are still under the new Enterobacterales (without an i) order, but divided into multiple families. The way tests are performed now by this [mdro()] function makes sure that results from before 2016 and after 2016 are identical.
#'
#' @section Using Custom Guidelines:
#'
#' Custom guidelines can be set with the [custom_mdro_guideline()] function. This is of great importance if you have custom rules to determine MDROs in your hospital, e.g., rules that are dependent on ward, state of contact isolation or other variables in your data.
#'
#' If you are familiar with `case_when()` of the `dplyr` package, you will recognise the input method to set your own rules. Rules must be set using what \R considers to be the 'formula notation':
#'
#' ```
#' custom <- custom_mdro_guideline(CIP == "R" & age > 60 ~ "Elderly Type A",
#' ERY == "R" & age > 60 ~ "Elderly Type B")
#' ```
#'
#' If a row/an isolate matches the first rule, the value after the first `~` (in this case *'Elderly Type A'*) will be set as MDRO value. Otherwise, the second rule will be tried and so on. The number of rules is unlimited.
#'
#' You can print the rules set in the console for an overview. Colours will help reading it if your console supports colours.
#'
#' ```
#' custom
#' #> A set of custom MDRO rules:
#' #> 1. CIP is "R" and age is higher than 60 -> Elderly Type A
#' #> 2. ERY is "R" and age is higher than 60 -> Elderly Type B
#' #> 3. Otherwise -> Negative
#' #>
#' #> Unmatched rows will return NA.
#' ```
#'
#' The outcome of the function can be used for the `guideline` argument in the [mdro()] function:
#'
#' ```
#' x <- mdro(example_isolates, guideline = custom)
#' table(x)
#' #> Elderly Type A Elderly Type B Negative
#' #> 43 891 1066
#' ```
#'
#' The rules set (the `custom` object in this case) could be exported to a shared file location using [saveRDS()] if you collaborate with multiple users. The custom rules set could then be imported using [readRDS()].
#' @inheritSection as.rsi Interpretation of R and S/I
#' @return
#' - CMI 2012 paper - function [mdr_cmi2012()] or [mdro()]:\cr
@@ -62,40 +117,71 @@
#' Ordered [factor] with levels `Negative` < `Mono-resistant` < `Poly-resistant` < `Multi-drug-resistant` < `Extensively drug-resistant`
#' - German guideline - function [mrgn()] or [`mdro(..., guideline = "MRGN")`][mdro()]:\cr
#' Ordered [factor] with levels `Negative` < `3MRGN` < `4MRGN`
#' - Everything else:\cr
#' - Everything else, except for custom guidelines:\cr
#' Ordered [factor] with levels `Negative` < `Positive, unconfirmed` < `Positive`. The value `"Positive, unconfirmed"` means that, according to the guideline, it is not entirely sure if the isolate is multi-drug resistant and this should be confirmed with additional (e.g. molecular) tests
#' @rdname mdro
#' @aliases MDR XDR PDR BRMO 3MRGN 4MRGN
#' @export
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @source
#' Please see *Details* for the list of publications used for this function.
#' See the supported guidelines above for the list of publications used for this function.
#' @examples
#' mdro(example_isolates, guideline = "EUCAST")
#'
#' mdro(example_isolates,
#' guideline = custom_mdro_guideline(AMX == "R" ~ "Custom MDRO 1",
#' VAN == "R" ~ "Custom MDRO 2"))
#'
#' \donttest{
#' if (require("dplyr")) {
#' example_isolates %>%
#' mdro() %>%
#' table()
#'
#' # no need to define `x` when used inside dplyr verbs:
#' example_isolates %>%
#' mutate(EUCAST = eucast_exceptional_phenotypes(.),
#' BRMO = brmo(.),
#' MRGN = mrgn(.))
#' mutate(MDRO = mdro(),
#' EUCAST = eucast_exceptional_phenotypes(),
#' BRMO = brmo(),
#' MRGN = mrgn())
#' }
#' }
mdro <- function(x,
mdro <- function(x = NULL,
guideline = "CMI2012",
col_mo = NULL,
info = interactive(),
pct_required_classes = 0.5,
combine_SI = TRUE,
verbose = FALSE,
only_rsi_columns = FALSE,
...) {
if (is_null_or_grouped_tbl(x)) {
# when `x` is left blank, auto determine it (get_current_data() also contains dplyr::cur_data_all())
# is also fix for using a grouped df as input (a dot as first argument)
x <- tryCatch(get_current_data(arg_name = "x", call = -2), error = function(e) x)
}
meet_criteria(x, allow_class = "data.frame") # also checks dimensions to be >0
meet_criteria(guideline, allow_class = c("list", "character"), allow_NULL = TRUE)
if (!is.list(guideline)) {
meet_criteria(guideline, allow_class = "character", has_length = 1, allow_NULL = TRUE)
}
meet_criteria(col_mo, allow_class = "character", has_length = 1, is_in = colnames(x), allow_NULL = TRUE)
meet_criteria(info, allow_class = "logical", has_length = 1)
meet_criteria(pct_required_classes, allow_class = "numeric", has_length = 1)
meet_criteria(combine_SI, allow_class = "logical", has_length = 1)
meet_criteria(verbose, allow_class = "logical", has_length = 1)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
check_dataset_integrity()
info.bak <- info
if (message_not_thrown_before("mdro")) {
remember_thrown_message("mdro")
} else {
# don't thrown info's more than once per call
info <- FALSE
}
if (interactive() & verbose == TRUE & info == TRUE) {
txt <- paste0("WARNING: In Verbose mode, the mdro() function does not return the MDRO results, but instead returns a data set in logbook form with extensive info about which isolates would be MDRO-positive, or why they are not.",
"\n\nThis may overwrite your existing data if you use e.g.:",
@@ -107,30 +193,81 @@ mdro <- function(x,
q_continue <- utils::menu(choices = c("OK", "Cancel"), graphics = FALSE, title = txt)
}
if (q_continue %in% c(FALSE, 2)) {
message("Cancelled, returning original data")
message_("Cancelled, returning original data", add_fn = font_red, as_note = FALSE)
return(x)
}
}
stop_ifnot(is.data.frame(x), "`x` must be a data.frame")
stop_if(any(dim(x) == 0), "`x` must contain rows and columns")
group_msg <- ""
if (info.bak == TRUE) {
# print group name if used in dplyr::group_by()
cur_group <- import_fn("cur_group", "dplyr", error_on_fail = FALSE)
if (!is.null(cur_group)) {
group_df <- tryCatch(cur_group(), error = function(e) data.frame())
if (NCOL(group_df) > 0) {
# transform factors to characters
group <- vapply(FUN.VALUE = character(1), group_df, function(x) {
if (is.numeric(x)) {
format(x)
} else if (is.logical(x)) {
as.character(x)
} else {
paste0('"', x, '"')
}
})
group_msg <- paste0("\nGroup: ", paste0(names(group), " = ", group, collapse = ", "), "\n")
}
}
}
# force regular data.frame, not a tibble or data.table
x <- as.data.frame(x, stringsAsFactors = FALSE)
stop_ifnot(is.numeric(pct_required_classes), "`pct_required_classes` must be numeric")
if (pct_required_classes > 1) {
# allow pct_required_classes = 75 -> pct_required_classes = 0.75
pct_required_classes <- pct_required_classes / 100
}
if (!is.null(list(...)$country)) {
warning("Using `country` is deprecated, use `guideline` instead. Please see ?mdro.", call. = FALSE)
warning_("Using `country` is deprecated, use `guideline` instead. See ?mdro.", call = FALSE)
guideline <- list(...)$country
}
stop_ifnot(length(guideline) == 1, "`guideline` must be of length 1")
guideline.bak <- guideline
if (is.list(guideline)) {
# Custom MDRO guideline ---------------------------------------------------
stop_ifnot(inherits(guideline, "custom_mdro_guideline"), "use `custom_mdro_guideline()` to create custom guidelines")
if (info == TRUE) {
txt <- paste0("Determining MDROs based on custom rules",
ifelse(isTRUE(attributes(guideline)$as_factor),
paste0(", resulting in factor levels: ", paste0(attributes(guideline)$values, collapse = " < ")),
""),
".")
txt <- word_wrap(txt)
cat(txt, "\n", sep = "")
}
x <- run_custom_mdro_guideline(x, guideline)
if (info.bak == TRUE) {
cat(group_msg)
if (sum(!is.na(x$MDRO)) == 0) {
cat(word_wrap(font_bold(paste0("=> Found 0 MDROs since no isolates are covered by the custom guideline"))))
} else {
cat(word_wrap(font_bold(paste0("=> Found ", sum(x$MDRO != "Negative", na.rm = TRUE),
" custom defined MDROs out of ", sum(!is.na(x$MDRO)),
" isolates (",
trimws(percentage(sum(x$MDRO != "Negative", na.rm = TRUE) / sum(!is.na(x$MDRO)))),
")\n"))))
}
}
if (verbose == TRUE) {
return(x[, c("row_number",
"MDRO",
"reason",
"columns_nonsusceptible")])
} else {
return(x$MDRO)
}
}
guideline <- tolower(gsub("[^a-zA-Z0-9.]+", "", guideline))
if (is.null(guideline)) {
# default to the paper by Magiorakos et al. (2012)
@@ -156,9 +293,9 @@ mdro <- function(x,
col_mo <- search_type_in_df(x = x, type = "mo", info = info)
}
if (is.null(col_mo) & guideline$code == "tb") {
message(font_blue("NOTE: No column found as input for `col_mo`,",
font_bold("assuming all records contain", font_italic("Mycobacterium tuberculosis."))))
x$mo <- as.mo("Mycobacterium tuberculosis")
message_("No column found as input for `col_mo`, ",
font_bold(paste0("assuming all records contain", font_italic("Mycobacterium tuberculosis"), ".")))
x$mo <- as.mo("Mycobacterium tuberculosis") # consider overkill at all times: MO_lookup[which(MO_lookup$fullname == "Mycobacterium tuberculosis"), "mo", drop = TRUE]
col_mo <- "mo"
}
stop_if(is.null(col_mo), "`col_mo` must be set")
@@ -167,39 +304,45 @@ mdro <- function(x,
if (guideline$code == "cmi2012") {
guideline$name <- "Multidrug-resistant, extensively drug-resistant and pandrug-resistant bacteria: an international expert proposal for interim standard definitions for acquired resistance."
guideline$author <- "Magiorakos AP, Srinivasan A, Carey RB, ..., Vatopoulos A, Weber JT, Monnet DL"
guideline$version <- "N/A"
guideline$source <- "Clinical Microbiology and Infection 18:3, 2012. DOI: 10.1111/j.1469-0691.2011.03570.x"
} else if (guideline$code == "eucast3.2") {
guideline$name <- "EUCAST Expert Rules, \"Intrinsic Resistance and Unusual Phenotypes\""
guideline$author <- "EUCAST (European Committee on Antimicrobial Susceptibility Testing)"
guideline$version <- "3.2, 2020"
guideline$source <- "https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/2020/Intrinsic_Resistance_and_Unusual_Phenotypes_Tables_v3.2_20200225.pdf"
guideline$version <- NA
guideline$source_url <- "Clinical Microbiology and Infection 18:3, 2012; doi: 10.1111/j.1469-0691.2011.03570.x"
guideline$type <- "MDRs/XDRs/PDRs"
} else if (guideline$code == "eucast3.1") {
guideline$name <- "EUCAST Expert Rules, \"Intrinsic Resistance and Exceptional Phenotypes Tables\""
guideline$author <- "EUCAST (European Committee on Antimicrobial Susceptibility Testing)"
guideline$version <- "3.1, 2016"
guideline$source <- "https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/Expert_rules_intrinsic_exceptional_V3.1.pdf"
guideline$source_url <- "https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/Expert_rules_intrinsic_exceptional_V3.1.pdf"
guideline$type <- "EUCAST Exceptional Phenotypes"
} else if (guideline$code == "eucast3.2") {
guideline$name <- "EUCAST Expert Rules, \"Intrinsic Resistance and Unusual Phenotypes\""
guideline$author <- "EUCAST (European Committee on Antimicrobial Susceptibility Testing)"
guideline$version <- "3.2, 2020"
guideline$source_url <- "https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Expert_Rules/2020/Intrinsic_Resistance_and_Unusual_Phenotypes_Tables_v3.2_20200225.pdf"
guideline$type <- "EUCAST Unusual Phenotypes"
} else if (guideline$code == "tb") {
guideline$name <- "Companion handbook to the WHO guidelines for the programmatic management of drug-resistant tuberculosis"
guideline$author <- "WHO (World Health Organization)"
guideline$version <- "WHO/HTM/TB/2014.11, 2014"
guideline$source <- "https://www.who.int/tb/publications/pmdt_companionhandbook/en/"
guideline$source_url <- "https://www.who.int/tb/publications/pmdt_companionhandbook/en/"
guideline$type <- "MDR-TB's"
# support per country:
} else if (guideline$code == "mrgn") {
guideline$name <- "Cross-border comparison of the Dutch and German guidelines on multidrug-resistant Gram-negative microorganisms"
guideline$author <- "M\u00fcller J, Voss A, K\u00f6ck R, ..., Kern WV, Wendt C, Friedrich AW"
guideline$version <- "N/A"
guideline$source <- "Antimicrobial Resistance and Infection Control 4:7, 2015. DOI: 10.1186/s13756-015-0047-6"
guideline$version <- NA
guideline$source_url <- "Antimicrobial Resistance and Infection Control 4:7, 2015; doi: 10.1186/s13756-015-0047-6"
guideline$type <- "MRGNs"
} else if (guideline$code == "brmo") {
guideline$name <- "WIP-Richtlijn Bijzonder Resistente Micro-organismen (BRMO)"
guideline$author <- "RIVM (Rijksinstituut voor de Volksgezondheid)"
guideline$version <- "Revision as of December 2017"
guideline$source <- "https://www.rivm.nl/Documenten_en_publicaties/Professioneel_Praktisch/Richtlijnen/Infectieziekten/WIP_Richtlijnen/WIP_Richtlijnen/Ziekenhuizen/WIP_richtlijn_BRMO_Bijzonder_Resistente_Micro_Organismen_ZKH"
guideline$source_url <- "https://www.rivm.nl/Documenten_en_publicaties/Professioneel_Praktisch/Richtlijnen/Infectieziekten/WIP_Richtlijnen/WIP_Richtlijnen/Ziekenhuizen/WIP_richtlijn_BRMO_Bijzonder_Resistente_Micro_Organismen_ZKH"
guideline$type <- "BRMOs"
} else {
stop("This guideline is currently unsupported: ", guideline$code, call. = FALSE)
}
@@ -323,6 +466,7 @@ mdro <- function(x,
"MNO"),
verbose = verbose,
info = info,
only_rsi_columns = only_rsi_columns,
...)
} else if (guideline$code == "eucast3.2") {
cols_ab <- get_column_abx(x = x,
@@ -348,8 +492,9 @@ mdro <- function(x,
"TOB",
"TZD",
"VAN"),
info = info,
verbose = verbose,
info = info,
only_rsi_columns = only_rsi_columns,
...)
} else if (guideline$code == "tb") {
cols_ab <- get_column_abx(x = x,
@@ -361,8 +506,9 @@ mdro <- function(x,
"RIF",
"RIB",
"RFP"),
info = info,
verbose = verbose,
info = info,
only_rsi_columns = only_rsi_columns,
...)
} else if (guideline$code == "mrgn") {
cols_ab <- get_column_abx(x = x,
@@ -374,14 +520,17 @@ mdro <- function(x,
"CIP"),
verbose = verbose,
info = info,
only_rsi_columns = only_rsi_columns,
...)
} else {
cols_ab <- get_column_abx(x = x,
verbose = verbose,
info = info,
only_rsi_columns = only_rsi_columns,
...)
}
# nolint start
AMC <- cols_ab["AMC"]
AMK <- cols_ab["AMK"]
AMP <- cols_ab["AMP"]
@@ -524,6 +673,7 @@ mdro <- function(x,
abx_tb <- c(CAP, ETH, GAT, INH, PZA, RIF, RIB, RFP)
abx_tb <- abx_tb[!is.na(abx_tb)]
stop_if(guideline$code == "tb" & length(abx_tb) == 0, "no antimycobacterials found in data set")
# nolint end
if (combine_SI == TRUE) {
search_result <- "R"
@@ -537,12 +687,14 @@ mdro <- function(x,
} else {
cat(font_red("\nResults with 'R' or 'I' are considered as resistance. Use `combine_SI = TRUE` to only consider 'R' as resistance.\n"))
}
cat("\nDetermining multidrug-resistant organisms (MDRO), according to:\n",
font_bold("Guideline: "), font_italic(guideline$name), "\n",
font_bold("Version: "), guideline$version, "\n",
font_bold("Author: "), guideline$author, "\n",
font_bold("Source: "), guideline$source, "\n",
"\n", sep = "")
cat("\n", word_wrap("Determining multidrug-resistant organisms (MDRO), according to:"), "\n",
word_wrap(paste0(font_bold("Guideline: "), font_italic(guideline$name)), extra_indent = 11, as_note = FALSE), "\n",
word_wrap(paste0(font_bold("Author(s): "), guideline$author), extra_indent = 11, as_note = FALSE), "\n",
ifelse(!is.na(guideline$version),
paste0(word_wrap(paste0(font_bold("Version: "), guideline$version), extra_indent = 11, as_note = FALSE), "\n"),
""),
paste0(font_bold("Source: "), guideline$source_url),
"\n\n", sep = "")
}
ab_missing <- function(ab) {
@@ -551,10 +703,14 @@ mdro <- function(x,
ab_NA <- function(x) {
x[!is.na(x)]
}
verbose_df <- NULL
try_ab <- function(expr) {
out <- tryCatch(expr, error = function(e) FALSE)
out[is.na(out)] <- FALSE
out
}
# antibiotic classes
# nolint start
aminoglycosides <- c(TOB, GEN)
cephalosporins <- c(CDZ, CAC, CEC, CFR, RID, MAN, CTZ, CZD, CZO, CDR, DIT, FEP, CAT, CFM, CMX, CMZ, DIZ, CID, CFP, CSL, CND, CTX, CTT, CTF, FOX, CPM, CPO, CPD, CPR, CRD, CFS, CPT, CAZ, CCV, CTL, CTB, CZX, BPR, CFM1, CEI, CRO, CXM, LEX, CEP, HAP, CED, LTM, LOR)
cephalosporins_1st <- c(CAC, CFR, RID, CTZ, CZD, CZO, CRD, CTL, LEX, CEP, HAP, CED)
@@ -562,16 +718,20 @@ mdro <- function(x,
cephalosporins_3rd <- c(CDZ, CDR, DIT, CAT, CFM, CMX, DIZ, CFP, CSL, CTX, CPM, CPD, CFS, CAZ, CCV, CTB, CZX, CRO, LTM)
carbapenems <- c(DOR, ETP, IPM, MEM, MEV)
fluoroquinolones <- c(CIP, ENX, FLE, GAT, GEM, GRX, LVX, LOM, MFX, NOR, OFX, PAZ, PEF, PRU, RFL, SPX, TMX, TVA)
# nolint end
# helper function for editing the table
trans_tbl <- function(to, rows, cols, any_all) {
cols <- cols[!ab_missing(cols)]
cols <- cols[!is.na(cols)]
if (length(rows) > 0 & length(cols) > 0) {
x[, cols] <- as.data.frame(lapply(x[, cols, drop = FALSE], function(col) as.rsi(col)))
x[rows, "columns_nonsusceptible"] <<- sapply(rows,
x[, cols] <- as.data.frame(lapply(x[, cols, drop = FALSE],
function(col) as.rsi(col)),
stringsAsFactors = FALSE)
x[rows, "columns_nonsusceptible"] <<- vapply(FUN.VALUE = character(1),
rows,
function(row, group_vct = cols) {
cols_nonsus <- sapply(x[row, group_vct, drop = FALSE],
cols_nonsus <- vapply(FUN.VALUE = logical(1), x[row, group_vct, drop = FALSE],
function(y) y %in% search_result)
paste(sort(c(unlist(strsplit(x[row, "columns_nonsusceptible", drop = TRUE], ", ")),
names(cols_nonsus)[cols_nonsus])),
@@ -583,8 +743,9 @@ mdro <- function(x,
} else if (any_all == "all") {
search_function <- all
}
x_transposed <- as.list(as.data.frame(t(x[, cols, drop = FALSE])))
row_filter <- sapply(x_transposed, function(y) search_function(y %in% search_result, na.rm = TRUE))
x_transposed <- as.list(as.data.frame(t(x[, cols, drop = FALSE]),
stringsAsFactors = FALSE))
row_filter <- vapply(FUN.VALUE = logical(1), x_transposed, function(y) search_function(y %in% search_result, na.rm = TRUE))
row_filter <- x[which(row_filter), "row_number", drop = TRUE]
rows <- rows[rows %in% row_filter]
x[rows, "MDRO"] <<- to
@@ -593,45 +754,54 @@ mdro <- function(x,
}
trans_tbl2 <- function(txt, rows, lst) {
if (info == TRUE) {
message(font_blue(txt, "..."), appendLF = FALSE)
message_(txt, "...", appendLF = FALSE, as_note = FALSE)
}
if (length(rows) > 0) {
# function specific for the CMI paper of 2012 (Magiorakos et al.)
lst_vector <- unlist(lst)[!is.na(unlist(lst))]
x[, lst_vector] <- as.data.frame(lapply(x[, lst_vector, drop = FALSE], function(col) as.rsi(col)))
x[, lst_vector] <- as.data.frame(lapply(x[, lst_vector, drop = FALSE],
function(col) as.rsi(col)),
stringsAsFactors = FALSE)
x[rows, "classes_in_guideline"] <<- length(lst)
x[rows, "classes_available"] <<- sapply(rows,
x[rows, "classes_available"] <<- vapply(FUN.VALUE = double(1),
rows,
function(row, group_tbl = lst) {
sum(sapply(group_tbl, function(group) any(unlist(x[row, group[!is.na(group)], drop = TRUE]) %in% c("S", "I", "R"))))
sum(vapply(FUN.VALUE = logical(1),
group_tbl,
function(group) any(unlist(x[row, group[!is.na(group)], drop = TRUE]) %in% c("S", "I", "R"))))
})
if (verbose == TRUE) {
x[rows, "columns_nonsusceptible"] <<- sapply(rows,
x[rows, "columns_nonsusceptible"] <<- vapply(FUN.VALUE = character(1),
rows,
function(row, group_vct = lst_vector) {
cols_nonsus <- sapply(x[row, group_vct, drop = FALSE], function(y) y %in% search_result)
cols_nonsus <- vapply(FUN.VALUE = logical(1), x[row, group_vct, drop = FALSE], function(y) y %in% search_result)
paste(sort(names(cols_nonsus)[cols_nonsus]), collapse = ", ")
})
}
x[rows, "classes_affected"] <<- sapply(rows,
x[rows, "classes_affected"] <<- vapply(FUN.VALUE = double(1),
rows,
function(row, group_tbl = lst) {
sum(sapply(group_tbl,
sum(vapply(FUN.VALUE = logical(1),
group_tbl,
function(group) {
any(unlist(x[row, group[!is.na(group)], drop = TRUE]) %in% search_result, na.rm = TRUE)
}),
na.rm = TRUE)
})
# for PDR; all agents are R (or I if combine_SI = FALSE)
x_transposed <- as.list(as.data.frame(t(x[rows, lst_vector, drop = FALSE])))
row_filter <- sapply(x_transposed, function(y) all(y %in% search_result, na.rm = TRUE))
x_transposed <- as.list(as.data.frame(t(x[rows, lst_vector, drop = FALSE]),
stringsAsFactors = FALSE))
row_filter <- vapply(FUN.VALUE = logical(1), x_transposed, function(y) all(y %in% search_result, na.rm = TRUE))
x[which(row_filter), "classes_affected"] <<- 999
}
if (info == TRUE) {
message(font_blue(" OK"))
message_(" OK.", add_fn = list(font_green, font_bold), as_note = FALSE)
}
}
x[, col_mo] <- as.mo(x[, col_mo, drop = TRUE])
x[, col_mo] <- as.mo(as.character(x[, col_mo, drop = TRUE]))
# join to microorganisms data set
x <- left_join_microorganisms(x, by = col_mo)
x$MDRO <- ifelse(!is.na(x$genus), 1, NA_integer_)
@@ -647,20 +817,20 @@ mdro <- function(x,
# take amoxicillin if ampicillin is unavailable
if (is.na(AMP) & !is.na(AMX)) {
if (verbose == TRUE) {
message(font_blue("NOTE: Filling ampicillin (AMP) results with amoxicillin (AMX) results"))
message_("Filling ampicillin (AMP) results with amoxicillin (AMX) results")
}
AMP <- AMX
}
# take ceftriaxone if cefotaxime is unavailable and vice versa
if (is.na(CRO) & !is.na(CTX)) {
if (verbose == TRUE) {
message(font_blue("NOTE: Filling ceftriaxone (CRO) results with cefotaxime (CTX) results"))
message_("Filling ceftriaxone (CRO) results with cefotaxime (CTX) results")
}
CRO <- CTX
}
if (is.na(CTX) & !is.na(CRO)) {
if (verbose == TRUE) {
message(font_blue("NOTE: Filling cefotaxime (CTX) results with ceftriaxone (CRO) results"))
message_("Filling cefotaxime (CTX) results with ceftriaxone (CRO) results")
}
CTX <- CRO
}
@@ -674,6 +844,7 @@ mdro <- function(x,
x[which(x$genus == "Escherichia" & x$species == "hermannii"), ab_NA(c(TCC, TZP))] <- NA
x[which((x$genus == "Citrobacter" & x$species == "freundii")
| (x$genus == "Enterobacter" & x$species == "aerogenes")
| (x$genus == "Klebsiella" & x$species == "aerogenes") # new name (2017)
| (x$genus == "Enterobacter" & x$species == "cloacae")
| (x$genus == "Hafnia" & x$species == "alvei")
| (x$genus == "Morganella" & x$species == "morganii")
@@ -693,6 +864,7 @@ mdro <- function(x,
x[which((x$genus == "Citrobacter" & x$species == "koseri")
| (x$genus == "Citrobacter" & x$species == "freundii")
| (x$genus == "Enterobacter" & x$species == "aerogenes")
| (x$genus == "Klebsiella" & x$species == "aerogenes") # new name (2017)
| (x$genus == "Enterobacter" & x$species == "cloacae")
| (x$genus == "Escherichia" & x$species == "hermannii")
| (x$genus == "Hafnia" & x$species == "alvei")
@@ -705,6 +877,7 @@ mdro <- function(x,
| (x$genus == "Serratia" & x$species == "marcescens")), ab_NA(AMP)] <- NA
x[which((x$genus == "Citrobacter" & x$species == "freundii")
| (x$genus == "Enterobacter" & x$species == "aerogenes")
| (x$genus == "Klebsiella" & x$species == "aerogenes") # new name (2017)
| (x$genus == "Enterobacter" & x$species == "cloacae")
| (x$genus == "Hafnia" & x$species == "alvei")
| (x$genus == "Morganella" & x$species == "morganii")
@@ -714,6 +887,7 @@ mdro <- function(x,
x[which((x$genus == "Citrobacter" & x$species == "freundii")
| (x$genus == "Citrobacter" & x$species == "koseri")
| (x$genus == "Enterobacter" & x$species == "aerogenes")
| (x$genus == "Klebsiella" & x$species == "aerogenes") # new name (2017)
| (x$genus == "Enterobacter" & x$species == "cloacae")
| (x$genus == "Hafnia" & x$species == "alvei")
| (x$genus == "Providencia" & x$species == "rettgeri")
@@ -825,7 +999,9 @@ mdro <- function(x,
# MDR (=2): >=3 classes affected
x[which(x$classes_affected >= 3), "MDRO"] <- 2
if (verbose == TRUE) {
x[which(x$classes_affected >= 3), "reason"] <- paste0("at least 3 classes contain R or I: ", x$classes_affected[which(x$classes_affected >= 3)],
x[which(x$classes_affected >= 3), "reason"] <- paste0("at least 3 classes contain R",
ifelse(!isTRUE(combine_SI), " or I", ""), ": ",
x$classes_affected[which(x$classes_affected >= 3)],
" out of ", x$classes_available[which(x$classes_affected >= 3)], " available classes")
}
@@ -994,51 +1170,57 @@ mdro <- function(x,
if (guideline$code == "mrgn") {
# Germany -----------------------------------------------------------------
CTX_or_CAZ <- CTX %or% CAZ
IPM_or_MEM <- IPM %or% MEM
x$missing <- NA_character_
if (is.na(PIP)) PIP <- "missing"
if (is.na(CTX_or_CAZ)) CTX_or_CAZ <- "missing"
if (is.na(IPM_or_MEM)) IPM_or_MEM <- "missing"
if (is.na(IPM)) IPM <- "missing"
if (is.na(MEM)) MEM <- "missing"
if (is.na(CIP)) CIP <- "missing"
# Table 1
x[which((x$order == "Enterobacterales" | # following in fact the old Enterobacteriaceae classification
(x$genus == "Acinetobacter" & x$species == "baumannii")) &
x[, PIP] == "R" &
x[, CTX_or_CAZ] == "R" &
x[, IPM_or_MEM] == "S" &
x[, CIP] == "R"),
"MDRO"] <- 2 # 2 = 3MRGN
trans_tbl(2, # 3MRGN
which((x$order == "Enterobacterales" | # following in fact the old Enterobacteriaceae classification
(x$genus == "Acinetobacter" & x$species == "baumannii")) &
try_ab(x[, PIP, drop = TRUE] == "R") &
(try_ab(x[, CTX, drop = TRUE] == "R") | try_ab(x[, CAZ, drop = TRUE] == "R")) &
(try_ab(x[, IPM, drop = TRUE] != "R") | try_ab(x[, MEM, drop = TRUE] != "R")) &
try_ab(x[, CIP, drop = TRUE] == "R")),
c(PIP, CTX, CAZ, IPM, MEM, CIP),
"any")
x[which((x$order == "Enterobacterales" | # following in fact the old Enterobacteriaceae classification
(x$genus == "Acinetobacter" & x$species == "baumannii")) &
x[, PIP] == "R" &
x[, CTX_or_CAZ] == "R" &
x[, IPM_or_MEM] == "R" &
x[, CIP] == "R"),
"MDRO"] <- 3 # 3 = 4MRGN, overwrites 3MRGN if applicable
trans_tbl(3, # 4MRGN, overwrites 3MRGN if applicable
which((x$order == "Enterobacterales" | # following in fact the old Enterobacteriaceae classification
(x$genus == "Acinetobacter" & x$species == "baumannii")) &
try_ab(x[, PIP, drop = TRUE] == "R") &
(try_ab(x[, CTX, drop = TRUE] == "R") | try_ab(x[, CAZ, drop = TRUE] == "R")) &
(try_ab(x[, IPM, drop = TRUE] == "R") | try_ab(x[, MEM, drop = TRUE] == "R")) &
try_ab(x[, CIP, drop = TRUE] == "R")),
c(PIP, CTX, CAZ, IPM, MEM, CIP),
"any")
x[which((x$order == "Enterobacterales" | # following in fact the old Enterobacteriaceae classification
(x$genus == "Acinetobacter" & x$species == "baumannii")) &
x[, IPM] == "R" | x[, MEM] == "R"),
"MDRO"] <- 3 # 3 = 4MRGN, always when imipenem or meropenem is R
trans_tbl(3, # 4MRGN, overwrites 3MRGN if applicable
which((x$order == "Enterobacterales" | # following in fact the old Enterobacteriaceae classification
(x$genus == "Acinetobacter" & x$species == "baumannii")) &
(try_ab(x[, IPM, drop = TRUE] == "R") | try_ab(x[, MEM, drop = TRUE] == "R"))),
c(IPM, MEM),
"any")
x[which(x$genus == "Pseudomonas" & x$species == "aeruginosa" &
(x[, PIP] == "S") +
(x[, CTX_or_CAZ] == "S") +
(x[, IPM_or_MEM] == "S") +
(x[, CIP] == "S") == 1),
"MDRO"] <- 2 # 2 = 3MRGN, if only 1 group is S
trans_tbl(2, # 3MRGN, if only 1 group is S
which(x$genus == "Pseudomonas" & x$species == "aeruginosa" &
try_ab(x[, PIP, drop = TRUE] == "S") +
try_ab(x[, CTX, drop = TRUE] == "S") +
try_ab(x[, CAZ, drop = TRUE] == "S") +
try_ab(x[, IPM, drop = TRUE] == "S") +
try_ab(x[, MEM, drop = TRUE] == "S") +
try_ab(x[, CIP, drop = TRUE] == "S") == 1),
c(PIP, CTX, CAZ, IPM, MEM, CIP),
"any")
x[which((x$genus == "Pseudomonas" & x$species == "aeruginosa") &
x[, PIP] == "R" &
x[, CTX_or_CAZ] == "R" &
x[, IPM_or_MEM] == "R" &
x[, CIP] == "R"),
"MDRO"] <- 3 # 3 = 4MRGN
trans_tbl(3, # 4MRGN otherwise
which((x$genus == "Pseudomonas" & x$species == "aeruginosa") &
try_ab(x[, PIP, drop = TRUE] == "R") &
(try_ab(x[, CTX, drop = TRUE] == "R") | try_ab(x[, CAZ, drop = TRUE] == "R")) &
(try_ab(x[, IPM, drop = TRUE] == "R") | try_ab(x[, MEM, drop = TRUE] == "R")) &
try_ab(x[, CIP, drop = TRUE] == "R")),
c(PIP, CTX, CAZ, IPM, MEM, CIP),
"any")
x[which(x$MDRO == 2), "reason"] <- "3MRGN"
x[which(x$MDRO == 3), "reason"] <- "4MRGN"
}
if (guideline$code == "brmo") {
@@ -1091,17 +1273,21 @@ mdro <- function(x,
& !ab_missing(CAZ)
& !ab_missing(TZP)) {
x$psae <- 0
x[which(x[, MEM] == "R" | x[, IPM] == "R"), "psae"] <- 1 + x[which(x[, MEM] == "R" | x[, IPM] == "R"), "psae"]
x[which(x[, GEN] == "R" & x[, TOB] == "R"), "psae"] <- 1 + x[which(x[, GEN] == "R" & x[, TOB] == "R"), "psae"]
x[which(x[, CIP] == "R"), "psae"] <- 1 + x[which(x[, CIP] == "R"), "psae"]
x[which(x[, CAZ] == "R"), "psae"] <- 1 + x[which(x[, CAZ] == "R"), "psae"]
x[which(x[, TZP] == "R"), "psae"] <- 1 + x[which(x[, TZP] == "R"), "psae"]
x[which(x[, MEM, drop = TRUE] == "R" | x[, IPM, drop = TRUE] == "R"), "psae"] <- 1 + x[which(x[, MEM, drop = TRUE] == "R" | x[, IPM, drop = TRUE] == "R"), "psae"]
x[which(x[, GEN, drop = TRUE] == "R" & x[, TOB, drop = TRUE] == "R"), "psae"] <- 1 + x[which(x[, GEN, drop = TRUE] == "R" & x[, TOB, drop = TRUE] == "R"), "psae"]
x[which(x[, CIP, drop = TRUE] == "R"), "psae"] <- 1 + x[which(x[, CIP, drop = TRUE] == "R"), "psae"]
x[which(x[, CAZ, drop = TRUE] == "R"), "psae"] <- 1 + x[which(x[, CAZ, drop = TRUE] == "R"), "psae"]
x[which(x[, TZP, drop = TRUE] == "R"), "psae"] <- 1 + x[which(x[, TZP, drop = TRUE] == "R"), "psae"]
} else {
x$psae <- 0
}
trans_tbl(3,
which(x$genus == "Pseudomonas" & x$species == "aeruginosa" & x$psae >= 3),
c(CAZ, CIP, GEN, IPM, MEM, TOB, TZP),
"any")
x[which(
x$genus == "Pseudomonas" & x$species == "aeruginosa"
& x$psae >= 3), "MDRO"] <- 3
& x$psae >= 3), "reason"] <- paste0("at least 3 classes contain R", ifelse(!isTRUE(combine_SI), " or I", ""))
# Table 3
trans_tbl(3,
@@ -1176,13 +1362,15 @@ mdro <- function(x,
1))))
# keep all real TB, make other species NA
x$MDRO <- ifelse(x$fullname == "Mycobacterium tuberculosis", x$MDRO, NA_real_)
x$reason <- "PDR/MDR/XDR criteria were met"
}
if (info == TRUE) {
if (sum(!is.na(x$MDRO) == 0)) {
if (info.bak == TRUE) {
cat(group_msg)
if (sum(!is.na(x$MDRO)) == 0) {
cat(font_bold(paste0("=> Found 0 MDROs since no isolates are covered by the guideline")))
} else {
cat(font_bold(paste0("=> Found ", sum(x$MDRO %in% c(2:5), na.rm = TRUE), " MDROs out of ", sum(!is.na(x$MDRO)),
cat(font_bold(paste0("=> Found ", sum(x$MDRO %in% c(2:5), na.rm = TRUE), " ", guideline$type, " out of ", sum(!is.na(x$MDRO)),
" isolates (", trimws(percentage(sum(x$MDRO %in% c(2:5), na.rm = TRUE) / sum(!is.na(x$MDRO)))), ")\n")))
}
}
@@ -1199,8 +1387,11 @@ mdro <- function(x,
# Results ----
if (guideline$code == "cmi2012") {
if (any(x$MDRO == -1, na.rm = TRUE)) {
warning("NA introduced for isolates where the available percentage of antimicrobial classes was below ",
percentage(pct_required_classes), " (set with `pct_required_classes`)")
if (message_not_thrown_before("mdro.availability")) {
warning_("NA introduced for isolates where the available percentage of antimicrobial classes was below ",
percentage(pct_required_classes), " (set with `pct_required_classes`)", call = FALSE)
remember_thrown_message("mdro.availability")
}
# set these -1s to NA
x[which(x$MDRO == -1), "MDRO"] <- NA_integer_
}
@@ -1232,8 +1423,8 @@ mdro <- function(x,
col_mo,
"MDRO",
"reason",
"columns_nonsusceptible")]
#x
"columns_nonsusceptible"),
drop = FALSE]
} else {
x$MDRO
}
@@ -1242,30 +1433,173 @@ mdro <- function(x,
#' @rdname mdro
#' @export
brmo <- function(x, guideline = "BRMO", ...) {
mdro(x, guideline = "BRMO", ...)
custom_mdro_guideline <- function(..., as_factor = TRUE) {
dots <- tryCatch(list(...),
error = function(e) "error")
stop_if(identical(dots, "error"),
"rules must be a valid formula inputs (e.g., using '~'), see `?mdro`")
n_dots <- length(dots)
stop_if(n_dots == 0, "no custom rules were set. Please read the documentation using `?mdro`.")
out <- vector("list", n_dots)
for (i in seq_len(n_dots)) {
stop_ifnot(inherits(dots[[i]], "formula"),
"rule ", i, " must be a valid formula input (e.g., using '~'), see `?mdro`")
# Query
qry <- dots[[i]][[2]]
if (inherits(qry, "call")) {
qry <- as.expression(qry)
}
qry <- as.character(qry)
# these will prevent vectorisation, so replace them:
qry <- gsub("&&", "&", qry, fixed = TRUE)
qry <- gsub("||", "|", qry, fixed = TRUE)
# support filter()-like writing: custom_mdro_guideline('CIP == "R", AMX == "S"' ~ "result 1")
qry <- gsub(" *, *", " & ", qry)
# format nicely, setting spaces around operators
qry <- gsub(" *([&|+-/*^><==]+) *", " \\1 ", qry)
qry <- gsub("'", "\"", qry, fixed = TRUE)
out[[i]]$query <- as.expression(qry)
# Value
val <- tryCatch(eval(dots[[i]][[3]]), error = function(e) NULL)
stop_if(is.null(val), "rule ", i, " must return a valid value, it now returns an error: ", tryCatch(eval(dots[[i]][[3]]), error = function(e) e$message))
stop_if(length(val) > 1, "rule ", i, " must return a value of length 1, not ", length(val))
out[[i]]$value <- as.character(val)
}
names(out) <- paste0("rule", seq_len(n_dots))
out <- set_clean_class(out, new_class = c("custom_mdro_guideline", "list"))
attr(out, "values") <- c("Negative", vapply(FUN.VALUE = character(1), out, function(x) x$value))
attr(out, "as_factor") <- as_factor
out
}
#' @method print custom_mdro_guideline
#' @export
#' @noRd
print.custom_mdro_guideline <- function(x, ...) {
cat("A set of custom MDRO rules:\n")
for (i in seq_len(length(x))) {
rule <- x[[i]]
rule$query <- gsub(" & ", font_black(font_italic(" and ")), rule$query, fixed = TRUE)
rule$query <- gsub(" | ", font_black(" or "), rule$query, fixed = TRUE)
rule$query <- gsub(" + ", font_black(" plus "), rule$query, fixed = TRUE)
rule$query <- gsub(" - ", font_black(" minus "), rule$query, fixed = TRUE)
rule$query <- gsub(" / ", font_black(" divided by "), rule$query, fixed = TRUE)
rule$query <- gsub(" * ", font_black(" times "), rule$query, fixed = TRUE)
rule$query <- gsub(" == ", font_black(" is "), rule$query, fixed = TRUE)
rule$query <- gsub(" > ", font_black(" is higher than "), rule$query, fixed = TRUE)
rule$query <- gsub(" < ", font_black(" is lower than "), rule$query, fixed = TRUE)
rule$query <- gsub(" >= ", font_black(" is higher than or equal to "), rule$query, fixed = TRUE)
rule$query <- gsub(" <= ", font_black(" is lower than or equal to "), rule$query, fixed = TRUE)
rule$query <- gsub(" ^ ", font_black(" to the power of "), rule$query, fixed = TRUE)
# replace the black colour 'stops' with blue colour 'starts'
rule$query <- gsub("\033[39m", "\033[34m", as.character(rule$query), fixed = TRUE)
cat(" ", i, ". ", font_blue(rule$query), font_bold(" -> "), font_red(rule$value), "\n", sep = "")
}
cat(" ", i + 1, ". Otherwise", font_bold(" -> "), font_red(paste0("Negative")), "\n", sep = "")
cat("\nUnmatched rows will return ", font_red("NA"), ".\n", sep = "")
if (isTRUE(attributes(x)$as_factor)) {
cat("Results will be of class <factor>, with ordered levels: ", paste0(attributes(x)$values, collapse = " < "), "\n", sep = "")
} else {
cat("Results will be of class <character>.\n")
}
}
run_custom_mdro_guideline <- function(df, guideline) {
n_dots <- length(guideline)
stop_if(n_dots == 0, "no custom guidelines set", call = -2)
out <- character(length = NROW(df))
reasons <- character(length = NROW(df))
for (i in seq_len(n_dots)) {
qry <- tryCatch(eval(parse(text = guideline[[i]]$query), envir = df, enclos = parent.frame()),
error = function(e) {
pkg_env$err_msg <- e$message
return("error")
})
if (identical(qry, "error")) {
warning_("in custom_mdro_guideline(): rule ", i,
" (`", guideline[[i]]$query, "`) was ignored because of this error message: ",
pkg_env$err_msg,
call = FALSE,
add_fn = font_red)
next
}
stop_ifnot(is.logical(qry), "in custom_mdro_guideline(): rule ", i, " (`", guideline[[i]]$query,
"`) must return `TRUE` or `FALSE`, not ",
format_class(class(qry), plural = FALSE), call = FALSE)
val <- guideline[[i]]$value
out[which(qry)] <- val
reasons[which(qry)] <- paste0("matched rule ", gsub("rule", "", names(guideline)[i]), ": ", as.character(guideline[[i]]$query))
}
out[out == ""] <- "Negative"
reasons[out == "Negative"] <- "no rules matched"
if (isTRUE(attributes(guideline)$as_factor)) {
out <- factor(out, levels = attributes(guideline)$values, ordered = TRUE)
}
rsi_cols <- vapply(FUN.VALUE = logical(1), df, function(x) is.rsi(x))
columns_nonsusceptible <- as.data.frame(t(df[, rsi_cols] == "R"))
columns_nonsusceptible <- vapply(FUN.VALUE = character(1),
columns_nonsusceptible,
function(x) paste0(rownames(columns_nonsusceptible)[which(x)], collapse = " "))
columns_nonsusceptible[is.na(out)] <- NA_character_
data.frame(row_number = seq_len(NROW(df)),
MDRO = out,
reason = reasons,
columns_nonsusceptible = columns_nonsusceptible,
stringsAsFactors = FALSE)
}
#' @rdname mdro
#' @export
mrgn <- function(x, guideline = "MRGN", ...) {
mdro(x = x, guideline = "MRGN", ...)
brmo <- function(x = NULL, only_rsi_columns = FALSE, ...) {
meet_criteria(x, allow_class = "data.frame", allow_NULL = TRUE)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
stop_if("guideline" %in% names(list(...)),
"argument `guideline` must not be set since this is a guideline-specific function")
mdro(x = x, only_rsi_columns = only_rsi_columns, guideline = "BRMO", ...)
}
#' @rdname mdro
#' @export
mdr_tb <- function(x, guideline = "TB", ...) {
mdro(x = x, guideline = "TB", ...)
mrgn <- function(x = NULL, only_rsi_columns = FALSE, ...) {
meet_criteria(x, allow_class = "data.frame", allow_NULL = TRUE)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
stop_if("guideline" %in% names(list(...)),
"argument `guideline` must not be set since this is a guideline-specific function")
mdro(x = x, only_rsi_columns = only_rsi_columns, guideline = "MRGN", ...)
}
#' @rdname mdro
#' @export
mdr_cmi2012 <- function(x, guideline = "CMI2012", ...) {
mdro(x = x, guideline = "CMI2012", ...)
mdr_tb <- function(x = NULL, only_rsi_columns = FALSE, ...) {
meet_criteria(x, allow_class = "data.frame", allow_NULL = TRUE)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
stop_if("guideline" %in% names(list(...)),
"argument `guideline` must not be set since this is a guideline-specific function")
mdro(x = x, only_rsi_columns = only_rsi_columns, guideline = "TB", ...)
}
#' @rdname mdro
#' @export
eucast_exceptional_phenotypes <- function(x, guideline = "EUCAST", ...) {
mdro(x = x, guideline = "EUCAST", ...)
mdr_cmi2012 <- function(x = NULL, only_rsi_columns = FALSE, ...) {
meet_criteria(x, allow_class = "data.frame", allow_NULL = TRUE)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
stop_if("guideline" %in% names(list(...)),
"argument `guideline` must not be set since this is a guideline-specific function")
mdro(x = x, only_rsi_columns = only_rsi_columns, guideline = "CMI2012", ...)
}
#' @rdname mdro
#' @export
eucast_exceptional_phenotypes <- function(x = NULL, only_rsi_columns = FALSE, ...) {
meet_criteria(x, allow_class = "data.frame", allow_NULL = TRUE)
meet_criteria(only_rsi_columns, allow_class = "logical", has_length = 1)
stop_if("guideline" %in% names(list(...)),
"argument `guideline` must not be set since this is a guideline-specific function")
mdro(x = x, only_rsi_columns = only_rsi_columns, guideline = "EUCAST", ...)
}
+56 -38
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,13 +20,13 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Transform input to minimum inhibitory concentrations (MIC)
#' Transform Input to Minimum Inhibitory Concentrations (MIC)
#'
#' This transforms a vector to a new class [`mic`], which is an ordered [factor] with valid minimum inhibitory concentrations (MIC) as levels. Invalid MIC values will be translated as `NA` with a warning.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @rdname as.mic
#' @param x vector
#' @param na.rm a logical indicating whether missing values should be removed
@@ -35,7 +35,7 @@
#' @aliases mic
#' @export
#' @seealso [as.rsi()]
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' mic_data <- as.mic(c(">=32", "1.0", "1", "1.00", 8, "<=0.128", "8", "16", "16"))
#' is.mic(mic_data)
@@ -56,10 +56,13 @@
#' plot(mic_data)
#' barplot(mic_data)
as.mic <- function(x, na.rm = FALSE) {
meet_criteria(x, allow_class = c("mic", "character", "numeric", "integer"), allow_NA = TRUE)
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
if (is.mic(x)) {
x
} else {
x <- x %pm>% unlist()
x <- unlist(x)
if (na.rm == TRUE) {
x <- x[!is.na(x)]
}
@@ -104,14 +107,14 @@ as.mic <- function(x, na.rm = FALSE) {
# these are allowed MIC values and will become factor levels
ops <- c("<", "<=", "", ">=", ">")
lvls <- c(c(t(sapply(ops, function(x) paste0(x, "0.00", 1:9)))),
unique(c(t(sapply(ops, function(x) paste0(x, sort(as.double(paste0("0.0",
lvls <- c(c(t(vapply(FUN.VALUE = character(9), ops, function(x) paste0(x, "0.00", 1:9)))),
unique(c(t(vapply(FUN.VALUE = character(104), ops, function(x) paste0(x, sort(as.double(paste0("0.0",
sort(c(1:99, 125, 128, 256, 512, 625)))))))))),
unique(c(t(sapply(ops, function(x) paste0(x, sort(as.double(paste0("0.",
unique(c(t(vapply(FUN.VALUE = character(103), ops, function(x) paste0(x, sort(as.double(paste0("0.",
c(1:99, 125, 128, 256, 512))))))))),
c(t(sapply(ops, function(x) paste0(x, sort(c(1:9, 1.5)))))),
c(t(sapply(ops, function(x) paste0(x, c(10:98)[9:98 %% 2 == TRUE])))),
c(t(sapply(ops, function(x) paste0(x, sort(c(2 ^ c(7:10), 80 * c(2:12))))))))
c(t(vapply(FUN.VALUE = character(10), ops, function(x) paste0(x, sort(c(1:9, 1.5)))))),
c(t(vapply(FUN.VALUE = character(45), ops, function(x) paste0(x, c(10:98)[9:98 %% 2 == TRUE])))),
c(t(vapply(FUN.VALUE = character(15), ops, function(x) paste0(x, sort(c(2 ^ c(7:10), 80 * c(2:12))))))))
na_before <- x[is.na(x) | x == ""] %pm>% length()
x[!x %in% lvls] <- NA
@@ -120,23 +123,26 @@ as.mic <- function(x, na.rm = FALSE) {
if (na_before != na_after) {
list_missing <- x.bak[is.na(x) & !is.na(x.bak) & x.bak != ""] %pm>%
unique() %pm>%
sort()
list_missing <- paste0('"', list_missing, '"', collapse = ", ")
warning(na_after - na_before, " results truncated (",
round(((na_after - na_before) / length(x)) * 100),
"%) that were invalid MICs: ",
list_missing, call. = FALSE)
sort() %pm>%
vector_and(quotes = TRUE)
warning_(na_after - na_before, " results truncated (",
round(((na_after - na_before) / length(x)) * 100),
"%) that were invalid MICs: ",
list_missing, call = FALSE)
}
structure(.Data = factor(x, levels = lvls, ordered = TRUE),
class = c("mic", "ordered", "factor"))
set_clean_class(factor(x, levels = lvls, ordered = TRUE),
new_class = c("mic", "ordered", "factor"))
}
}
all_valid_mics <- function(x) {
if (!inherits(x, c("mic", "character", "factor", "numeric", "integer"))) {
return(FALSE)
}
x_mic <- tryCatch(suppressWarnings(as.mic(x[!is.na(x)])),
error = function(e) NA)
!any(is.na(x_mic)) & !all(is.na(x))
!any(is.na(x_mic)) && !all(is.na(x))
}
#' @rdname as.mic
@@ -149,27 +155,27 @@ is.mic <- function(x) {
#' @export
#' @noRd
as.double.mic <- function(x, ...) {
as.double(gsub("(<|=|>)+", "", as.character(x)))
as.double(gsub("[<=>]+", "", as.character(x)))
}
#' @method as.integer mic
#' @export
#' @noRd
as.integer.mic <- function(x, ...) {
as.integer(gsub("(<|=|>)+", "", as.character(x)))
as.integer(gsub("[<=>]+", "", as.character(x)))
}
#' @method as.numeric mic
#' @export
#' @noRd
as.numeric.mic <- function(x, ...) {
as.numeric(gsub("(<|=|>)+", "", as.character(x)))
as.numeric(gsub("[<=>]+", "", as.character(x)))
}
#' @method droplevels mic
#' @export
#' @noRd
droplevels.mic <- function(x, exclude = ifelse(anyNA(levels(x)), NULL, NA), ...) {
droplevels.mic <- function(x, exclude = if (any(is.na(levels(x)))) NULL else NA, ...) {
x <- droplevels.factor(x, exclude = exclude, ...)
class(x) <- c("mic", "ordered", "factor")
x
@@ -177,9 +183,13 @@ droplevels.mic <- function(x, exclude = ifelse(anyNA(levels(x)), NULL, NA), ...)
# will be exported using s3_register() in R/zzz.R
pillar_shaft.mic <- function(x, ...) {
out <- trimws(format(x))
crude_numbers <- as.double(x)
operators <- gsub("[^<=>]+", "", as.character(x))
pasted <- trimws(paste0(operators, trimws(format(crude_numbers))))
out <- pasted
out[is.na(x)] <- font_na(NA)
create_pillar_column(out, align = "right", min_width = 4)
out <- gsub("(<|=|>)", font_silver("\\1"), out)
create_pillar_column(out, align = "right", width = max(nchar(pasted)))
}
# will be exported using s3_register() in R/zzz.R
@@ -213,7 +223,7 @@ summary.mic <- function(object, ...) {
#' @method plot mic
#' @export
#' @importFrom graphics barplot axis par
#' @importFrom graphics barplot axis
#' @rdname plot
plot.mic <- function(x,
main = paste("MIC values of", deparse(substitute(x))),
@@ -221,13 +231,18 @@ plot.mic <- function(x,
xlab = "MIC value",
axes = FALSE,
...) {
barplot(table(droplevels.factor(x)),
meet_criteria(main, allow_class = "character", has_length = 1)
meet_criteria(ylab, allow_class = "character", has_length = 1)
meet_criteria(xlab, allow_class = "character", has_length = 1)
meet_criteria(axes, allow_class = "logical", has_length = 1)
barplot(table(as.double(x)),
ylab = ylab,
xlab = xlab,
axes = axes,
main = main,
...)
axis(2, seq(0, max(table(droplevels.factor(x)))))
axis(2, seq(0, max(table(as.double(x)))))
}
#' @method barplot mic
@@ -240,13 +255,18 @@ barplot.mic <- function(height,
xlab = "MIC value",
axes = FALSE,
...) {
barplot(table(droplevels.factor(height)),
meet_criteria(main, allow_class = "character", has_length = 1)
meet_criteria(ylab, allow_class = "character", has_length = 1)
meet_criteria(xlab, allow_class = "character", has_length = 1)
meet_criteria(axes, allow_class = "logical", has_length = 1)
barplot(table(as.double(height)),
ylab = ylab,
xlab = xlab,
axes = axes,
main = main,
...)
axis(2, seq(0, max(table(droplevels.factor(height)))))
axis(2, seq(0, max(table(as.double(height)))))
}
#' @method [ mic
@@ -303,14 +323,12 @@ unique.mic <- function(x, incomparables = FALSE, ...) {
# will be exported using s3_register() in R/zzz.R
get_skimmers.mic <- function(column) {
sfl <- import_fn("sfl", "skimr", error_on_fail = FALSE)
inline_hist <- import_fn("inline_hist", "skimr", error_on_fail = FALSE)
sfl(
skimr::sfl(
skim_type = "mic",
min = ~as.character(sort(na.omit(.))[1]),
min = ~as.character(sort(stats::na.omit(.))[1]),
max = ~as.character(sort(stats::na.omit(.))[length(stats::na.omit(.))]),
median = ~as.character(stats::na.omit(.)[as.double(stats::na.omit(.)) == median(as.double(stats::na.omit(.)))])[1],
n_unique = ~pm_n_distinct(., na.rm = TRUE),
hist_log2 = ~inline_hist(log2(as.double(stats::na.omit(.))))
hist_log2 = ~skimr::inline_hist(log2(as.double(stats::na.omit(.))))
)
}
+1292 -1161
View File
File diff suppressed because it is too large Load Diff
+20 -13
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,32 +20,36 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Calculate the matching score for microorganisms
#' Calculate the Matching Score for Microorganisms
#'
#' This helper function is used by [as.mo()] to determine the most probable match of taxonomic records, based on user input.
#' This algorithm is used by [as.mo()] and all the [`mo_*`][mo_property()] functions to determine the most probable match of taxonomic records based on user input.
#' @inheritSection lifecycle Stable Lifecycle
#' @author Matthijs S. Berends
#' @param x Any user input value(s)
#' @param n A full taxonomic name, that exists in [`microorganisms$fullname`][microorganisms]
#' @section Matching score for microorganisms:
#' @section Matching Score for Microorganisms:
#' With ambiguous user input in [as.mo()] and all the [`mo_*`][mo_property()] functions, the returned results are chosen based on their matching score using [mo_matching_score()]. This matching score \eqn{m}, is calculated as:
#'
#' \deqn{m_{(x, n)} = \frac{l_{n} - 0.5 \cdot \min \begin{cases}l_{n} \\ \textrm{lev}(x, n)\end{cases}}{l_{n} \cdot p_{n} \cdot k_{n}}}{m(x, n) = ( l_n * min(l_n, lev(x, n) ) ) / ( l_n * p_n * k_n )}
#' \ifelse{latex}{\deqn{m_{(x, n)} = \frac{l_{n} - 0.5 \cdot \min \begin{cases}l_{n} \\ \textrm{lev}(x, n)\end{cases}}{l_{n} \cdot p_{n} \cdot k_{n}}}}{\ifelse{html}{\figure{mo_matching_score.png}{options: width="300px" alt="mo matching score"}}{m(x, n) = ( l_n * min(l_n, lev(x, n) ) ) / ( l_n * p_n * k_n )}}
#'
#' where:
#'
#' * \eqn{x} is the user input;
#' * \eqn{n} is a taxonomic name (genus, species, and subspecies);
#' * \eqn{l_n}{l_n} is the length of \eqn{n};
#' * lev is the [Levenshtein distance function](https://en.wikipedia.org/wiki/Levenshtein_distance), which counts any insertion, deletion and substitution as 1 that is needed to change \eqn{x} into \eqn{n};
#' * \eqn{p_n}{p_n} is the human pathogenic prevalence group of \eqn{n}, as described below;
#' * \eqn{k_n}{p_n} is the taxonomic kingdom of \eqn{n}, set as Bacteria = 1, Fungi = 2, Protozoa = 3, Archaea = 4, others = 5.
#' * \ifelse{html}{\out{<i>x</i> is the user input;}}{\eqn{x} is the user input;}
#' * \ifelse{html}{\out{<i>n</i> is a taxonomic name (genus, species, and subspecies);}}{\eqn{n} is a taxonomic name (genus, species, and subspecies);}
#' * \ifelse{html}{\out{<i>l<sub>n</sub></i> is the length of <i>n</i>;}}{l_n is the length of \eqn{n};}
#' * \ifelse{html}{\out{<i>lev</i> is the <a href="https://en.wikipedia.org/wiki/Levenshtein_distance">Levenshtein distance function</a>, which counts any insertion, deletion and substitution as 1 that is needed to change <i>x</i> into <i>n</i>;}}{lev is the Levenshtein distance function, which counts any insertion, deletion and substitution as 1 that is needed to change \eqn{x} into \eqn{n};}
#' * \ifelse{html}{\out{<i>p<sub>n</sub></i> is the human pathogenic prevalence group of <i>n</i>, as described below;}}{p_n is the human pathogenic prevalence group of \eqn{n}, as described below;}
#' * \ifelse{html}{\out{<i>k<sub>n</sub></i> is the taxonomic kingdom of <i>n</i>, set as Bacteria = 1, Fungi = 2, Protozoa = 3, Archaea = 4, others = 5.}}{l_n is the taxonomic kingdom of \eqn{n}, set as Bacteria = 1, Fungi = 2, Protozoa = 3, Archaea = 4, others = 5.}
#'
#' The grouping into human pathogenic prevalence (\eqn{p}) is based on experience from several microbiological laboratories in the Netherlands in conjunction with international reports on pathogen prevalence. **Group 1** (most prevalent microorganisms) consists of all microorganisms where the taxonomic class is Gammaproteobacteria or where the taxonomic genus is *Enterococcus*, *Staphylococcus* or *Streptococcus*. This group consequently contains all common Gram-negative bacteria, such as *Pseudomonas* and *Legionella* and all species within the order Enterobacterales. **Group 2** consists of all microorganisms where the taxonomic phylum is Proteobacteria, Firmicutes, Actinobacteria or Sarcomastigophora, or where the taxonomic genus is *Absidia*, *Acremonium*, *Actinotignum*, *Alternaria*, *Anaerosalibacter*, *Apophysomyces*, *Arachnia*, *Aspergillus*, *Aureobacterium*, *Aureobasidium*, *Bacteroides*, *Basidiobolus*, *Beauveria*, *Blastocystis*, *Branhamella*, *Calymmatobacterium*, *Candida*, *Capnocytophaga*, *Catabacter*, *Chaetomium*, *Chryseobacterium*, *Chryseomonas*, *Chrysonilia*, *Cladophialophora*, *Cladosporium*, *Conidiobolus*, *Cryptococcus*, *Curvularia*, *Exophiala*, *Exserohilum*, *Flavobacterium*, *Fonsecaea*, *Fusarium*, *Fusobacterium*, *Hendersonula*, *Hypomyces*, *Koserella*, *Lelliottia*, *Leptosphaeria*, *Leptotrichia*, *Malassezia*, *Malbranchea*, *Mortierella*, *Mucor*, *Mycocentrospora*, *Mycoplasma*, *Nectria*, *Ochroconis*, *Oidiodendron*, *Phoma*, *Piedraia*, *Pithomyces*, *Pityrosporum*, *Prevotella*,\\*Pseudallescheria*, *Rhizomucor*, *Rhizopus*, *Rhodotorula*, *Scolecobasidium*, *Scopulariopsis*, *Scytalidium*,*Sporobolomyces*, *Stachybotrys*, *Stomatococcus*, *Treponema*, *Trichoderma*, *Trichophyton*, *Trichosporon*, *Tritirachium* or *Ureaplasma*. **Group 3** consists of all other microorganisms.
#'
#' All matches are sorted descending on their matching score and for all user input values, the top match will be returned. This will lead to the effect that e.g., `"E. coli"` will return the microbial ID of *Escherichia coli* (\eqn{m = `r round(mo_matching_score("E. coli", "Escherichia coli"), 3)`}, a highly prevalent microorganism found in humans) and not *Entamoeba coli* (\eqn{m = `r round(mo_matching_score("E. coli", "Entamoeba coli"), 3)`}, a less prevalent microorganism in humans), although the latter would alphabetically come first.
#' @export
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' as.mo("E. coli")
#' mo_uncertainties()
@@ -53,6 +57,9 @@
#' mo_matching_score(x = "E. coli",
#' n = c("Escherichia coli", "Entamoeba coli"))
mo_matching_score <- function(x, n) {
meet_criteria(x, allow_class = c("character", "data.frame", "list"))
meet_criteria(n, allow_class = "character")
x <- parse_and_convert(x)
# no dots and other non-whitespace characters
x <- gsub("[^a-zA-Z0-9 \\(\\)]+", "", x)
+346 -52
View File
@@ -1,15 +1,15 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
# Diagnostics & Advice, and University Medical Center Groningen. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
@@ -20,33 +20,38 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Get properties of a microorganism
#' Get Properties of a Microorganism
#'
#' Use these functions to return a specific property of a microorganism based on the latest accepted taxonomy. All input values will be evaluated internally with [as.mo()], which makes it possible to use microbial abbreviations, codes and names as input. Please see *Examples*.
#' @inheritSection lifecycle Stable lifecycle
#' @param x any (vector of) text that can be coerced to a valid microorganism code with [as.mo()]
#' @param property one of the column names of the [microorganisms] data set or `"shortname"`
#' @param language language of the returned text, defaults to system language (see [get_locale()]) and can be overwritten by setting the option `AMR_locale`, e.g. `options(AMR_locale = "de")`, see [translate]. Use `language = NULL` or `language = ""` to prevent translation.
#' @param ... other parameters passed on to [as.mo()], such as 'allow_uncertain' and 'ignore_pattern'
#' @param open browse the URL using [utils::browseURL()]
#' Use these functions to return a specific property of a microorganism based on the latest accepted taxonomy. All input values will be evaluated internally with [as.mo()], which makes it possible to use microbial abbreviations, codes and names as input. See *Examples*.
#' @inheritSection lifecycle Stable Lifecycle
#' @param x any character (vector) that can be coerced to a valid microorganism code with [as.mo()]. Can be left blank for auto-guessing the column containing microorganism codes if used in a data set, see *Examples*.
#' @param property one of the column names of the [microorganisms] data set: `r vector_or(colnames(microorganisms), sort = FALSE, quotes = TRUE)`, or must be `"shortname"`
#' @param language language of the returned text, defaults to system language (see [get_locale()]) and can be overwritten by setting the option `AMR_locale`, e.g. `options(AMR_locale = "de")`, see [translate]. Also used to translate text like "no growth". Use `language = NULL` or `language = ""` to prevent translation.
#' @param ... other arguments passed on to [as.mo()], such as 'allow_uncertain' and 'ignore_pattern'
#' @param ab any (vector of) text that can be coerced to a valid antibiotic code with [as.ab()]
#' @param open browse the URL using [`browseURL()`][utils::browseURL()]
#' @details All functions will return the most recently known taxonomic property according to the Catalogue of Life, except for [mo_ref()], [mo_authors()] and [mo_year()]. Please refer to this example, knowing that *Escherichia blattae* was renamed to *Shimwellia blattae* in 2010:
#' - `mo_name("Escherichia blattae")` will return `"Shimwellia blattae"` (with a message about the renaming)
#' - `mo_ref("Escherichia blattae")` will return `"Burgess et al., 1973"` (with a message about the renaming)
#' - `mo_ref("Shimwellia blattae")` will return `"Priest et al., 2010"` (without a message)
#'
#' The short name - [mo_shortname()] - almost always returns the first character of the genus and the full species, like `"E. coli"`. Exceptions are abbreviations of staphylococci (like *"CoNS"*, Coagulase-Negative Staphylococci) and beta-haemolytic streptococci (like *"GBS"*, Group B Streptococci). Please bear in mind that e.g. *E. coli* could mean *Escherichia coli* (kingdom of Bacteria) as well as *Entamoeba coli* (kingdom of Protozoa). Returning to the full name will be done using [as.mo()] internally, giving priority to bacteria and human pathogens, i.e. `"E. coli"` will be considered *Escherichia coli*. In other words, `mo_fullname(mo_shortname("Entamoeba coli"))` returns `"Escherichia coli"`.
#'
#' The short name - [mo_shortname()] - almost always returns the first character of the genus and the full species, like `"E. coli"`. Exceptions are abbreviations of staphylococci (such as *"CoNS"*, Coagulase-Negative Staphylococci) and beta-haemolytic streptococci (such as *"GBS"*, Group B Streptococci). Please bear in mind that e.g. *E. coli* could mean *Escherichia coli* (kingdom of Bacteria) as well as *Entamoeba coli* (kingdom of Protozoa). Returning to the full name will be done using [as.mo()] internally, giving priority to bacteria and human pathogens, i.e. `"E. coli"` will be considered *Escherichia coli*. In other words, `mo_fullname(mo_shortname("Entamoeba coli"))` returns `"Escherichia coli"`.
#'
#' Since the top-level of the taxonomy is sometimes referred to as 'kingdom' and sometimes as 'domain', the functions [mo_kingdom()] and [mo_domain()] return the exact same results.
#'
#' The Gram stain - [mo_gramstain()] - will be determined based on the taxonomic kingdom and phylum. According to Cavalier-Smith (2002, [PMID 11837318](https://pubmed.ncbi.nlm.nih.gov/11837318)), who defined subkingdoms Negibacteria and Posibacteria, only these phyla are Posibacteria: Actinobacteria, Chloroflexi, Firmicutes and Tenericutes. These bacteria are considered Gram-positive - all other bacteria are considered Gram-negative. Species outside the kingdom of Bacteria will return a value `NA`.
#' The Gram stain - [mo_gramstain()] - will be determined based on the taxonomic kingdom and phylum. According to Cavalier-Smith (2002, [PMID 11837318](https://pubmed.ncbi.nlm.nih.gov/11837318)), who defined subkingdoms Negibacteria and Posibacteria, only these phyla are Posibacteria: Actinobacteria, Chloroflexi, Firmicutes and Tenericutes. These bacteria are considered Gram-positive - all other bacteria are considered Gram-negative. Species outside the kingdom of Bacteria will return a value `NA`. Functions [mo_is_gram_negative()] and [mo_is_gram_positive()] always return `TRUE` or `FALSE` (except when the input is `NA` or the MO code is `UNKNOWN`), thus always return `FALSE` for species outside the taxonomic kingdom of Bacteria.
#'
#' Determination of yeasts - [mo_is_yeast()] - will be based on the taxonomic kingdom and class. *Budding yeasts* are fungi of the phylum Ascomycetes, class Saccharomycetes (also called Hemiascomycetes). *True yeasts* are aggregated into the underlying order Saccharomycetales. Thus, for all microorganisms that are fungi and member of the taxonomic class Saccharomycetes, the function will return `TRUE`. It returns `FALSE` otherwise (except when the input is `NA` or the MO code is `UNKNOWN`).
#'
#' Intrinsic resistance - [mo_is_intrinsic_resistant()] - will be determined based on the [intrinsic_resistant] data set, which is based on `r format_eucast_version_nr(3.2)`. The [mo_is_intrinsic_resistant()] functions can be vectorised over arguments `x` (input for microorganisms) and over `ab` (input for antibiotics).
#'
#' All output will be [translate]d where possible.
#' All output [will be translated][translate] where possible.
#'
#' The function [mo_url()] will return the direct URL to the online database entry, which also shows the scientific reference of the concerned species.
#' @inheritSection mo_matching_score Matching score for microorganisms
#' @inheritSection mo_matching_score Matching Score for Microorganisms
#' @inheritSection catalogue_of_life Catalogue of Life
#' @inheritSection as.mo Source
#' @rdname mo_property
@@ -59,8 +64,8 @@
#' - A [character] in all other cases
#' @export
#' @seealso [microorganisms]
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # taxonomic tree -----------------------------------------------------------
#' mo_kingdom("E. coli") # "Bacteria"
@@ -122,7 +127,7 @@
#' mo_shortname("S. pyo", Lancefield = TRUE) # "GAS" (='Group A Streptococci')
#'
#'
#' # language support for German, Dutch, Spanish, Portuguese, Italian and French
#' # language support --------------------------------------------------------
#' mo_gramstain("E. coli", language = "de") # "Gramnegativ"
#' mo_gramstain("E. coli", language = "nl") # "Gram-negatief"
#' mo_gramstain("E. coli", language = "es") # "Gram negativo"
@@ -140,13 +145,37 @@
#' language = "nl") # "Streptococcus groep A"
#'
#'
#' # other --------------------------------------------------------------------
#'
#' mo_is_yeast(c("Candida", "E. coli")) # TRUE, FALSE
#'
#' # gram stains and intrinsic resistance can also be used as a filter in dplyr verbs
#' if (require("dplyr")) {
#' example_isolates %>%
#' filter(mo_is_gram_positive())
#'
#' example_isolates %>%
#' filter(mo_is_intrinsic_resistant(ab = "vanco"))
#' }
#'
#'
#' # get a list with the complete taxonomy (from kingdom to subspecies)
#' mo_taxonomy("E. coli")
#' # get a list with the taxonomy, the authors, Gram-stain and URL to the online database
#' mo_info("E. coli")
#' }
mo_name <- function(x, language = get_locale(), ...) {
translate_AMR(mo_validate(x = x, property = "fullname", language = language, ...), language = language, only_unknown = FALSE)
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_name")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = "fullname", language = language, ...),
language = language,
only_unknown = FALSE,
affect_mo_name = TRUE)
}
#' @rdname mo_property
@@ -156,6 +185,13 @@ mo_fullname <- mo_name
#' @rdname mo_property
#' @export
mo_shortname <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_shortname")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x.mo <- as.mo(x, language = language, ...)
metadata <- get_mo_failures_uncertainties_renamed()
@@ -171,63 +207,120 @@ mo_shortname <- function(x, language = get_locale(), ...) {
# exceptions for where no species is known
shortnames[shortnames %like% ".[.] spp[.]"] <- genera[shortnames %like% ".[.] spp[.]"]
# exceptions for Staphylococci
# exceptions for staphylococci
shortnames[shortnames == "S. coagulase-negative"] <- "CoNS"
shortnames[shortnames == "S. coagulase-positive"] <- "CoPS"
# exceptions for Streptococci: Streptococcus Group A -> GAS
# exceptions for streptococci: Group A Streptococcus -> GAS
shortnames[shortnames %like% "S. group [ABCDFGHK]"] <- paste0("G", gsub("S. group ([ABCDFGHK])", "\\1", shortnames[shortnames %like% "S. group [ABCDFGHK]"]), "S")
# unknown species etc.
shortnames[shortnames %like% "unknown"] <- paste0("(", trimws(gsub("[^a-zA-Z -]", "", shortnames[shortnames %like% "unknown"])), ")")
shortnames[is.na(x.mo)] <- NA_character_
load_mo_failures_uncertainties_renamed(metadata)
translate_AMR(shortnames, language = language, only_unknown = FALSE)
translate_AMR(shortnames, language = language, only_unknown = FALSE, affect_mo_name = TRUE)
}
#' @rdname mo_property
#' @export
mo_subspecies <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_subspecies")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = "subspecies", language = language, ...), language = language, only_unknown = TRUE)
}
#' @rdname mo_property
#' @export
mo_species <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_species")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = "species", language = language, ...), language = language, only_unknown = TRUE)
}
#' @rdname mo_property
#' @export
mo_genus <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_genus")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = "genus", language = language, ...), language = language, only_unknown = TRUE)
}
#' @rdname mo_property
#' @export
mo_family <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_family")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = "family", language = language, ...), language = language, only_unknown = TRUE)
}
#' @rdname mo_property
#' @export
mo_order <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_order")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = "order", language = language, ...), language = language, only_unknown = TRUE)
}
#' @rdname mo_property
#' @export
mo_class <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_class")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = "class", language = language, ...), language = language, only_unknown = TRUE)
}
#' @rdname mo_property
#' @export
mo_phylum <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_phylum")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = "phylum", language = language, ...), language = language, only_unknown = TRUE)
}
#' @rdname mo_property
#' @export
mo_kingdom <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_kingdom")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = "kingdom", language = language, ...), language = language, only_unknown = TRUE)
}
@@ -238,12 +331,29 @@ mo_domain <- mo_kingdom
#' @rdname mo_property
#' @export
mo_type <- function(x, language = get_locale(), ...) {
translate_AMR(mo_validate(x = x, property = "kingdom", language = language, ...), language = language, only_unknown = FALSE)
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_type")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x.mo <- as.mo(x, language = language, ...)
out <- mo_kingdom(x.mo, language = NULL)
out[which(mo_is_yeast(x.mo))] <- "Yeasts"
translate_AMR(out, language = language, only_unknown = FALSE)
}
#' @rdname mo_property
#' @export
mo_gramstain <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_gramstain")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x.mo <- as.mo(x, language = language, ...)
metadata <- get_mo_failures_uncertainties_renamed()
@@ -272,21 +382,141 @@ mo_gramstain <- function(x, language = get_locale(), ...) {
translate_AMR(x, language = language, only_unknown = FALSE)
}
#' @rdname mo_property
#' @export
mo_is_gram_negative <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_is_gram_negative")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x.mo <- as.mo(x, language = language, ...)
metadata <- get_mo_failures_uncertainties_renamed()
grams <- mo_gramstain(x.mo, language = NULL)
load_mo_failures_uncertainties_renamed(metadata)
out <- grams == "Gram-negative" & !is.na(grams)
out[x.mo %in% c(NA_character_, "UNKNOWN")] <- NA
out
}
#' @rdname mo_property
#' @export
mo_is_gram_positive <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_is_gram_positive")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x.mo <- as.mo(x, language = language, ...)
metadata <- get_mo_failures_uncertainties_renamed()
grams <- mo_gramstain(x.mo, language = NULL)
load_mo_failures_uncertainties_renamed(metadata)
out <- grams == "Gram-positive" & !is.na(grams)
out[x.mo %in% c(NA_character_, "UNKNOWN")] <- NA
out
}
#' @rdname mo_property
#' @export
mo_is_yeast <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_is_yeast")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x.mo <- as.mo(x, language = language, ...)
metadata <- get_mo_failures_uncertainties_renamed()
x.kingdom <- mo_kingdom(x.mo, language = NULL)
x.phylum <- mo_phylum(x.mo, language = NULL)
x.class <- mo_class(x.mo, language = NULL)
x.order <- mo_order(x.mo, language = NULL)
load_mo_failures_uncertainties_renamed(metadata)
out <- rep(FALSE, length(x))
out[x.kingdom == "Fungi" & x.class == "Saccharomycetes"] <- TRUE
out[x.mo %in% c(NA_character_, "UNKNOWN")] <- NA
out
}
#' @rdname mo_property
#' @export
mo_is_intrinsic_resistant <- function(x, ab, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_is_intrinsic_resistant")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(ab, allow_NA = FALSE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x <- as.mo(x, language = language, ...)
ab <- as.ab(ab, language = NULL, flag_multiple_results = FALSE, info = FALSE)
if (length(x) == 1 & length(ab) > 1) {
x <- rep(x, length(ab))
} else if (length(ab) == 1 & length(x) > 1) {
ab <- rep(ab, length(x))
}
if (length(x) != length(ab)) {
stop_("length of `x` and `ab` must be equal, or one of them must be of length 1.")
}
# show used version number once per session (pkg_env will reload every session)
if (message_not_thrown_before("intrinsic_resistant_version", entire_session = TRUE)) {
message_("Determining intrinsic resistance based on ",
format_eucast_version_nr(3.2, markdown = FALSE), ". ",
font_red("This note will be shown once per session."))
remember_thrown_message("intrinsic_resistant_version", entire_session = TRUE)
}
# runs against internal vector: INTRINSIC_R (see zzz.R)
paste(x, ab) %in% INTRINSIC_R
}
#' @rdname mo_property
#' @export
mo_snomed <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_snomed")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
mo_validate(x = x, property = "snomed", language = language, ...)
}
#' @rdname mo_property
#' @export
mo_ref <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_ref")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
mo_validate(x = x, property = "ref", language = language, ...)
}
#' @rdname mo_property
#' @export
mo_authors <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_authors")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x <- mo_validate(x = x, property = "ref", language = language, ...)
# remove last 4 digits and presumably the comma and space that preceed them
x[!is.na(x)] <- gsub(",? ?[0-9]{4}", "", x[!is.na(x)])
@@ -296,6 +526,13 @@ mo_authors <- function(x, language = get_locale(), ...) {
#' @rdname mo_property
#' @export
mo_year <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_year")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x <- mo_validate(x = x, property = "ref", language = language, ...)
# get last 4 digits
x[!is.na(x)] <- gsub(".*([0-9]{4})$", "\\1", x[!is.na(x)])
@@ -305,23 +542,37 @@ mo_year <- function(x, language = get_locale(), ...) {
#' @rdname mo_property
#' @export
mo_rank <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_rank")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
mo_validate(x = x, property = "rank", language = language, ...)
}
#' @rdname mo_property
#' @export
mo_taxonomy <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_taxonomy")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x <- as.mo(x, language = language, ...)
metadata <- get_mo_failures_uncertainties_renamed()
result <- list(kingdom = mo_kingdom(x, language = language),
phylum = mo_phylum(x, language = language),
class = mo_class(x, language = language),
order = mo_order(x, language = language),
family = mo_family(x, language = language),
genus = mo_genus(x, language = language),
species = mo_species(x, language = language),
subspecies = mo_subspecies(x, language = language))
phylum = mo_phylum(x, language = language),
class = mo_class(x, language = language),
order = mo_order(x, language = language),
family = mo_family(x, language = language),
genus = mo_genus(x, language = language),
species = mo_species(x, language = language),
subspecies = mo_subspecies(x, language = language))
load_mo_failures_uncertainties_renamed(metadata)
result
@@ -330,6 +581,13 @@ mo_taxonomy <- function(x, language = get_locale(), ...) {
#' @rdname mo_property
#' @export
mo_synonyms <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_synonyms")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x <- as.mo(x, language = language, ...)
metadata <- get_mo_failures_uncertainties_renamed()
@@ -356,6 +614,13 @@ mo_synonyms <- function(x, language = get_locale(), ...) {
#' @rdname mo_property
#' @export
mo_info <- function(x, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_info")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
x <- as.mo(x, language = language, ...)
metadata <- get_mo_failures_uncertainties_renamed()
@@ -379,12 +644,20 @@ mo_info <- function(x, language = get_locale(), ...) {
#' @rdname mo_property
#' @export
mo_url <- function(x, open = FALSE, language = get_locale(), ...) {
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_url")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(open, allow_class = "logical", has_length = 1)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
mo <- as.mo(x = x, language = language, ... = ...)
mo_names <- mo_name(mo)
metadata <- get_mo_failures_uncertainties_renamed()
df <- data.frame(mo, stringsAsFactors = FALSE) %pm>%
pm_left_join(pm_select(microorganisms, mo, source, species_id), by = "mo")
pm_left_join(pm_select(microorganisms, mo, source, species_id), by = "mo")
df$url <- ifelse(df$source == "CoL",
paste0(catalogue_of_life$url_CoL, "details/species/id/", df$species_id, "/"),
ifelse(df$source == "DSMZ",
@@ -395,7 +668,7 @@ mo_url <- function(x, open = FALSE, language = get_locale(), ...) {
if (open == TRUE) {
if (length(u) > 1) {
warning("only the first URL will be opened, as `browseURL()` only suports one string.")
warning_("Only the first URL will be opened, as `browseURL()` only suports one string.")
}
utils::browseURL(u[1L])
}
@@ -408,54 +681,75 @@ mo_url <- function(x, open = FALSE, language = get_locale(), ...) {
#' @rdname mo_property
#' @export
mo_property <- function(x, property = "fullname", language = get_locale(), ...) {
stop_ifnot(length(property) == 1L, "'property' must be of length 1")
stop_ifnot(property %in% colnames(microorganisms),
"invalid property: '", property, "' - use a column name of the `microorganisms` data set")
if (missing(x)) {
# this tries to find the data and an <mo> column
x <- find_mo_col(fn = "mo_property")
}
meet_criteria(x, allow_NA = TRUE)
meet_criteria(property, allow_class = "character", has_length = 1, is_in = colnames(microorganisms))
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE)
translate_AMR(mo_validate(x = x, property = property, language = language, ...), language = language, only_unknown = TRUE)
}
mo_validate <- function(x, property, language, ...) {
check_dataset_integrity()
if (tryCatch(all(x[!is.na(x)] %in% MO_lookup$mo) & length(list(...)) == 0, error = function(e) FALSE)) {
# special case for mo_* functions where class is already <mo>
return(MO_lookup[match(x, MO_lookup$mo), property, drop = TRUE])
}
dots <- list(...)
Becker <- dots$Becker
if (is.null(Becker)) {
if (is.null(Becker) | property %in% c("kingdom", "phylum", "class", "order", "family", "genus")) {
Becker <- FALSE
}
Lancefield <- dots$Lancefield
if (is.null(Lancefield)) {
if (is.null(Lancefield) | property %in% c("kingdom", "phylum", "class", "order", "family", "genus")) {
Lancefield <- FALSE
}
has_Becker_or_Lancefield <- Becker %in% c(TRUE, "all") | Lancefield %in% c(TRUE, "all")
# try to catch an error when inputting an invalid parameter
if (tryCatch(all(x[!is.na(x)] %in% MO_lookup$mo) & !has_Becker_or_Lancefield, error = function(e) FALSE)) {
# special case for mo_* functions where class is already <mo>
return(MO_lookup[match(x, MO_lookup$mo), property, drop = TRUE])
}
# try to catch an error when inputting an invalid argument
# so the 'call.' can be set to FALSE
tryCatch(x[1L] %in% MO_lookup[1, property, drop = TRUE],
error = function(e) stop(e$message, call. = FALSE))
if (is.mo(x)
& !Becker %in% c(TRUE, "all")
if (is.mo(x)
& !Becker %in% c(TRUE, "all")
& !Lancefield %in% c(TRUE, "all")) {
# this will not reset mo_uncertainties and mo_failures
# because it's already a valid MO
x <- exec_as.mo(x, property = property, initial_search = FALSE, language = language, ...)
} else if (!all(x %in% MO_lookup[, property, drop = TRUE])
| Becker %in% c(TRUE, "all")
| Lancefield %in% c(TRUE, "all")) {
| has_Becker_or_Lancefield) {
x <- exec_as.mo(x, property = property, language = language, ...)
}
if (property == "mo") {
return(to_class_mo(x))
return(set_clean_class(x, new_class = c("mo", "character")))
} else if (property == "snomed") {
return(as.double(eval(parse(text = x))))
} else {
return(x)
}
}
find_mo_col <- function(fn) {
# this function tries to find an mo column in the data the function was called in,
# which is useful when functions are used within dplyr verbs
df <- get_current_data(arg_name = "x", call = -3) # will return an error if not found
mo <- NULL
try({
mo <- suppressMessages(search_type_in_df(df, "mo"))
}, silent = TRUE)
if (!is.null(df) && !is.null(mo) && is.data.frame(df)) {
if (message_not_thrown_before(fn = fn)) {
message_("Using column '", font_bold(mo), "' as input for ", fn, "()")
remember_thrown_message(fn = fn)
}
return(df[, mo, drop = TRUE])
} else {
stop_("argument `x` is missing and no column with info about microorganisms could be found.", call = -2)
}
}
+105 -83
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,30 +20,31 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' User-defined reference data set for microorganisms
#' User-Defined Reference Data Set for Microorganisms
#'
#' @description These functions can be used to predefine your own reference to be used in [as.mo()] and consequently all `mo_*` functions like [mo_genus()] and [mo_gramstain()].
#' @description These functions can be used to predefine your own reference to be used in [as.mo()] and consequently all [`mo_*`][mo_property()] functions (such as [mo_genus()] and [mo_gramstain()]).
#'
#' This is **the fastest way** to have your organisation (or analysis) specific codes picked up and translated by this package.
#' @inheritSection lifecycle Stable lifecycle
#' @param path location of your reference file, see Details. Can be `""`, `NULL` or `FALSE` to delete the reference file.
#' This is **the fastest way** to have your organisation (or analysis) specific codes picked up and translated by this package, since you don't have to bother about it again after setting it up once.
#' @inheritSection lifecycle Stable Lifecycle
#' @param path location of your reference file, see *Details*. Can be `""`, `NULL` or `FALSE` to delete the reference file.
#' @param destination destination of the compressed data file, default to the user's home directory.
#' @rdname mo_source
#' @name mo_source
#' @aliases set_mo_source get_mo_source
#' @details The reference file can be a text file separated with commas (CSV) or tabs or pipes, an Excel file (either 'xls' or 'xlsx' format) or an R object file (extension '.rds'). To use an Excel file, you will need to have the `readxl` package installed.
#' @details The reference file can be a text file separated with commas (CSV) or tabs or pipes, an Excel file (either 'xls' or 'xlsx' format) or an \R object file (extension '.rds'). To use an Excel file, you will need to have the `readxl` package installed.
#'
#' [set_mo_source()] will check the file for validity: it must be a [data.frame], must have a column named `"mo"` which contains values from [`microorganisms$mo`][microorganisms] and must have a reference column with your own defined values. If all tests pass, [set_mo_source()] will read the file into R and will ask to export it to `"~/.mo_source.rds"`. The CRAN policy disallows packages to write to the file system, although '*exceptions may be allowed in interactive sessions if the package obtains confirmation from the user*'. For this reason, this function only works in interactive sessions so that the user can **specifically confirm and allow** that this file will be created.
#' [set_mo_source()] will check the file for validity: it must be a [data.frame], must have a column named `"mo"` which contains values from [`microorganisms$mo`][microorganisms] and must have a reference column with your own defined values. If all tests pass, [set_mo_source()] will read the file into \R and will ask to export it to `"~/mo_source.rds"`. The CRAN policy disallows packages to write to the file system, although '*exceptions may be allowed in interactive sessions if the package obtains confirmation from the user*'. For this reason, this function only works in interactive sessions so that the user can **specifically confirm and allow** that this file will be created. The destination of this file can be set with the `destination` argument and defaults to the user's home directory. It can also be set as an \R option, using `options(AMR_mo_source = "my/location/file.rds")`.
#'
#' The created compressed data file `"~/.mo_source.rds"` will be used at default for MO determination (function [as.mo()] and consequently all `mo_*` functions like [mo_genus()] and [mo_gramstain()]). The location of the original file will be saved as an R option with `options(mo_source = path)`. Its timestamp will be saved with `options(mo_source_datetime = ...)`.
#' The created compressed data file `"mo_source.rds"` will be used at default for MO determination (function [as.mo()] and consequently all `mo_*` functions like [mo_genus()] and [mo_gramstain()]). The location and timestamp of the original file will be saved as an attribute to the compressed data file.
#'
#' The function [get_mo_source()] will return the data set by reading `"~/.mo_source.rds"` with [readRDS()]. If the original file has changed (by checking the aforementioned options `mo_source` and `mo_source_datetime`), it will call [set_mo_source()] to update the data file automatically if used in an interactive session.
#' The function [get_mo_source()] will return the data set by reading `"mo_source.rds"` with [readRDS()]. If the original file has changed (by checking the location and timestamp of the original file), it will call [set_mo_source()] to update the data file automatically if used in an interactive session.
#'
#' Reading an Excel file (`.xlsx`) with only one row has a size of 8-9 kB. The compressed file created with [set_mo_source()] will then have a size of 0.1 kB and can be read by [get_mo_source()] in only a couple of microseconds (millionths of a second).
#'
#' @section How to setup:
#' @section How to Setup:
#'
#' Imagine this data on a sheet of an Excel file (mo codes were looked up in the [microorganisms] data set). The first column contains the organisation specific codes, the second column contains an MO code from this package:
#'
@@ -60,16 +61,18 @@
#'
#' ```
#' set_mo_source("home/me/ourcodes.xlsx")
#' #> NOTE: Created mo_source file '~/.mo_source.rds' from 'home/me/ourcodes.xlsx'
#' #> (columns "Organisation XYZ" and "mo")
#' #> NOTE: Created mo_source file '/Users/me/mo_source.rds' (0.3 kB) from
#' #> '/Users/me/Documents/ourcodes.xlsx' (9 kB), columns
#' #> "Organisation XYZ" and "mo"
#' ```
#'
#' It has now created a file `"~/.mo_source.rds"` with the contents of our Excel file. Only the first column with foreign values and the 'mo' column will be kept when creating the RDS file.
#' It has now created a file `"~/mo_source.rds"` with the contents of our Excel file. Only the first column with foreign values and the 'mo' column will be kept when creating the RDS file.
#'
#' And now we can use it in our functions:
#'
#' ```
#' as.mo("lab_mo_ecoli")
#' #> Class <mo>
#' #> [1] B_ESCHR_COLI
#'
#' mo_genus("lab_mo_kpneumoniae")
@@ -77,6 +80,9 @@
#'
#' # other input values still work too
#' as.mo(c("Escherichia coli", "E. coli", "lab_mo_ecoli"))
#' #> NOTE: Translation to one microorganism was guessed with uncertainty.
#' #> Use mo_uncertainties() to review it.
#' #> Class <mo>
#' #> [1] B_ESCHR_COLI B_ESCHR_COLI B_ESCHR_COLI
#' ```
#'
@@ -96,8 +102,10 @@
#'
#' ```
#' as.mo("lab_mo_ecoli")
#' #> NOTE: Updated mo_source file '~/.mo_source.rds' from 'home/me/ourcodes.xlsx'
#' #> (columns "Organisation XYZ" and "mo")
#' #> NOTE: Updated mo_source file '/Users/me/mo_source.rds' (0.3 kB) from
#' #> '/Users/me/Documents/ourcodes.xlsx' (9 kB), columns
#' #> "Organisation XYZ" and "mo"
#' #> Class <mo>
#' #> [1] B_ESCHR_COLI
#'
#' mo_genus("lab_Staph_aureus")
@@ -108,39 +116,41 @@
#'
#' ```
#' set_mo_source(NULL)
#' # Removed mo_source file '~/.mo_source.rds'.
#' #> Removed mo_source file '/Users/me/mo_source.rds'
#' ```
#'
#' If the original Excel file is moved or deleted, the mo_source file will be removed upon the next use of [as.mo()]. If the mo_source file is manually deleted (i.e. without using [set_mo_source()]), the references to the mo_source file will be removed upon the next use of [as.mo()].
#' If the original file (in the previous case an Excel file) is moved or deleted, the `mo_source.rds` file will be removed upon the next use of [as.mo()] or any [`mo_*`][mo_property()] function.
#' @export
#' @inheritSection AMR Read more on our website!
set_mo_source <- function(path) {
#' @inheritSection AMR Read more on Our Website!
set_mo_source <- function(path, destination = getOption("AMR_mo_source", "~/mo_source.rds")) {
meet_criteria(path, allow_class = "character", has_length = 1, allow_NULL = TRUE)
meet_criteria(destination, allow_class = "character", has_length = 1)
stop_ifnot(destination %like% "[.]rds$", "the `destination` must be a file location with file extension .rds.")
file_location <- path.expand("~/mo_source.rds")
stop_ifnot(interactive(), "This function can only be used in interactive mode, since it must ask for the user's permission to write a file to their home folder.")
stop_ifnot(length(path) == 1, "`path` must be of length 1")
mo_source_destination <- path.expand(destination)
stop_ifnot(interactive(), "this function can only be used in interactive mode, since it must ask for the user's permission to write a file to their home folder.")
if (is.null(path) || path %in% c(FALSE, "")) {
options(mo_source = NULL)
options(mo_source_timestamp = NULL)
if (file.exists(file_location)) {
unlink(file_location)
message(font_red(paste0("Removed mo_source file '", font_bold(file_location), "'")))
pkg_env$mo_source <- NULL
if (file.exists(mo_source_destination)) {
unlink(mo_source_destination)
message_("Removed mo_source file '", font_bold(mo_source_destination), "'",
add_fn = font_red,
as_note = FALSE)
}
return(invisible())
}
stop_ifnot(file.exists(path),
"file not found: ", path)
stop_ifnot(file.exists(path), "file not found: ", path)
if (path %like% "[.]rds$") {
df <- readRDS(path)
} else if (path %like% "[.]xlsx?$") {
# is Excel file (old or new)
read_excel <- import_fn("read_excel", "readxl")
df <- read_excel(path)
stop_ifnot_installed("readxl")
df <- readxl::read_excel(path)
} else if (path %like% "[.]tsv$") {
df <- utils::read.table(header = TRUE, sep = "\t", stringsAsFactors = FALSE)
@@ -150,13 +160,13 @@ set_mo_source <- function(path) {
try(
df <- utils::read.table(header = TRUE, sep = ",", stringsAsFactors = FALSE),
silent = TRUE)
if (!mo_source_isvalid(df, stop_on_error = FALSE)) {
if (!check_validity_mo_source(df, stop_on_error = FALSE)) {
# try tab
try(
df <- utils::read.table(header = TRUE, sep = "\t", stringsAsFactors = FALSE),
silent = TRUE)
}
if (!mo_source_isvalid(df, stop_on_error = FALSE)) {
if (!check_validity_mo_source(df, stop_on_error = FALSE)) {
# try pipe
try(
df <- utils::read.table(header = TRUE, sep = "|", stringsAsFactors = FALSE),
@@ -165,7 +175,7 @@ set_mo_source <- function(path) {
}
# check integrity
mo_source_isvalid(df)
check_validity_mo_source(df)
df <- subset(df, !is.na(mo))
@@ -177,18 +187,21 @@ set_mo_source <- function(path) {
}
df <- as.data.frame(df, stringAsFactors = FALSE)
df[, "mo"] <- set_clean_class(df[, "mo", drop = TRUE], c("mo", "character"))
# success
if (file.exists(file_location)) {
if (file.exists(mo_source_destination)) {
action <- "Updated"
} else {
action <- "Created"
# only ask when file is created, not when it is updated
txt <- paste0("This will write create the new file '",
file_location,
"', for which your permission is needed.\n\nDo you agree that this file will be created? ")
if ("rsasdtudioapi" %in% rownames(utils::installed.packages())) {
showQuestion <- import_fn("showQuestion", "rstudioapi")
txt <- paste0(word_wrap(paste0("This will write create the new file '",
mo_source_destination,
"', for which your permission is needed.")),
"\n\n",
word_wrap("Do you agree that this file will be created?"))
showQuestion <- import_fn("showQuestion", "rstudioapi", error_on_fail = FALSE)
if (!is.null(showQuestion)) {
q_continue <- showQuestion("Create new file in home directory", txt)
} else {
q_continue <- utils::menu(choices = c("OK", "Cancel"), graphics = FALSE, title = txt)
@@ -197,72 +210,67 @@ set_mo_source <- function(path) {
return(invisible())
}
}
saveRDS(df, file_location)
options(mo_source = path)
options(mo_source_timestamp = as.character(file.info(path)$mtime))
message(font_blue(paste0("NOTE: ",
action, " mo_source file '", font_bold(file_location), "'",
" from '", font_bold(path), "'",
'\n (columns "', colnames(df)[1], '" and "', colnames(df)[2], '")')))
attr(df, "mo_source_location") <- path
attr(df, "mo_source_destination") <- mo_source_destination
attr(df, "mo_source_timestamp") <- file.mtime(path)
saveRDS(df, mo_source_destination)
pkg_env$mo_source <- df
message_(action, " mo_source file '", font_bold(mo_source_destination),
"' (", formatted_filesize(mo_source_destination),
") from '", font_bold(path),
"' (", formatted_filesize(path),
'), columns "', colnames(df)[1], '" and "', colnames(df)[2], '"')
}
#' @rdname mo_source
#' @export
get_mo_source <- function() {
if (is.null(getOption("mo_source", NULL))) {
get_mo_source <- function(destination = getOption("AMR_mo_source", "~/mo_source.rds")) {
if (!file.exists(path.expand(destination))) {
if (interactive()) {
# source file might have been deleted, so update reference
set_mo_source("")
}
return(NULL)
}
if (!file.exists(path.expand("~/mo_source.rds"))) {
options(mo_source = NULL)
options(mo_source_timestamp = NULL)
message(font_blue("NOTE: Removed references to deleted mo_source file (see ?mo_source)"))
return(NULL)
if (is.null(pkg_env$mo_source)) {
pkg_env$mo_source <- readRDS(path.expand(destination))
}
old_time <- as.POSIXct(getOption("mo_source_timestamp"))
new_time <- as.POSIXct(as.character(file.info(getOption("mo_source", ""))$mtime))
if (is.na(new_time)) {
# source file was deleted, remove reference too
set_mo_source("")
return(NULL)
old_time <- attributes(pkg_env$mo_source)$mo_source_timestamp
new_time <- file.mtime(attributes(pkg_env$mo_source)$mo_source_location)
if (interactive() && !identical(old_time, new_time)) {
# source file was updated, also update reference
set_mo_source(attributes(pkg_env$mo_source)$mo_source_location)
}
if (interactive() && new_time != old_time) {
# set updated source
set_mo_source(getOption("mo_source"))
}
file_location <- path.expand("~/mo_source.rds")
readRDS(file_location)
pkg_env$mo_source
}
mo_source_isvalid <- function(x, refer_to_name = "`reference_df`", stop_on_error = TRUE) {
check_validity_mo_source <- function(x, refer_to_name = "`reference_df`", stop_on_error = TRUE) {
check_dataset_integrity()
if (deparse(substitute(x)) == "get_mo_source()") {
if (paste(deparse(substitute(x)), collapse = "") == "get_mo_source()") {
return(TRUE)
}
if (identical(x, get_mo_source())) {
if (is.null(pkg_env$mo_source) && (identical(x, get_mo_source()))) {
return(TRUE)
}
if (is.null(x)) {
if (stop_on_error == TRUE) {
stop(refer_to_name, " cannot be NULL", call. = FALSE)
stop_(refer_to_name, " cannot be NULL", call = FALSE)
} else {
return(FALSE)
}
}
if (!is.data.frame(x)) {
if (stop_on_error == TRUE) {
stop(refer_to_name, " must be a data.frame", call. = FALSE)
stop_(refer_to_name, " must be a data.frame", call = FALSE)
} else {
return(FALSE)
}
}
if (!"mo" %in% colnames(x)) {
if (stop_on_error == TRUE) {
stop(refer_to_name, " must contain a column 'mo'", call. = FALSE)
stop_(refer_to_name, " must contain a column 'mo'", call = FALSE)
} else {
return(FALSE)
}
@@ -275,13 +283,27 @@ mo_source_isvalid <- function(x, refer_to_name = "`reference_df`", stop_on_error
} else {
plural <- ""
}
stop("Value", plural, " ", paste0("'", invalid[, 1, drop = TRUE], "'", collapse = ", "),
stop_("Value", plural, " ", vector_and(invalid[, 1, drop = TRUE], quotes = TRUE),
" found in ", tolower(refer_to_name),
", but with invalid microorganism code", plural, " ", paste0("'", invalid$mo, "'", collapse = ", "),
call. = FALSE)
", but with invalid microorganism code", plural, " ", vector_and(invalid$mo, quotes = TRUE),
call = FALSE)
} else {
return(FALSE)
}
}
TRUE
if (colnames(x)[1] != "mo" & nrow(x) > length(unique(x[, 1, drop = TRUE]))) {
if (stop_on_error == TRUE) {
stop_(refer_to_name, " contains duplicate values in column '", colnames(x)[1], "'", call = FALSE)
} else {
return(FALSE)
}
}
if (colnames(x)[2] != "mo" & nrow(x) > length(unique(x[, 2, drop = TRUE]))) {
if (stop_on_error == TRUE) {
stop_(refer_to_name, " contains duplicate values in column '", colnames(x)[2], "'", call = FALSE)
} else {
return(FALSE)
}
}
return(TRUE)
}
+62 -20
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,13 +20,13 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Principal Component Analysis (for AMR)
#'
#' Performs a principal component analysis (PCA) based on a data set with automatic determination for afterwards plotting the groups and labels, and automatic filtering on only suitable (i.e. non-empty and numeric) variables.
#' @inheritSection lifecycle Maturing lifecycle
#' @inheritSection lifecycle Maturing Lifecycle
#' @param x a [data.frame] containing numeric columns
#' @param ... columns of `x` to be selected for PCA, can be unquoted since it supports quasiquotation.
#' @inheritParams stats::prcomp
@@ -36,8 +36,9 @@
#' @return An object of classes [pca] and [prcomp]
#' @importFrom stats prcomp
#' @export
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # `example_isolates` is a dataset available in the AMR package.
#' # `example_isolates` is a data set available in the AMR package.
#' # See ?example_isolates.
#'
#' \donttest{
@@ -46,7 +47,7 @@
#' # calculate the resistance per group first
#' resistance_data <- example_isolates %>%
#' group_by(order = mo_order(mo), # group on anything, like order
#' genus = mo_genus(mo)) %>% # and genus as we do here
#' genus = mo_genus(mo)) %>% # and genus as we do here;
#' summarise_if(is.rsi, resistance) # then get resistance of all drugs
#'
#' # now conduct PCA for certain antimicrobial agents
@@ -66,9 +67,12 @@ pca <- function(x,
scale. = TRUE,
tol = NULL,
rank. = NULL) {
stop_ifnot(is.data.frame(x), "`x` must be a data.frame")
stop_if(any(dim(x) == 0), "`x` must contain rows and columns")
meet_criteria(x, allow_class = "data.frame")
meet_criteria(retx, allow_class = "logical", has_length = 1)
meet_criteria(center, allow_class = "logical", has_length = 1)
meet_criteria(scale., allow_class = "logical", has_length = 1)
meet_criteria(tol, allow_class = "numeric", has_length = 1, allow_NULL = TRUE)
meet_criteria(rank., allow_class = "numeric", has_length = 1, allow_NULL = TRUE)
# unset data.table, tibble, etc.
# also removes groups made by dplyr::group_by
@@ -87,15 +91,15 @@ pca <- function(x,
# this is to support quoted variables: df %pm>% pca("mycol1", "mycol2")
new_list[[i]] <- x[, new_list[[i]]]
} else {
# remove item - it's a parameter like `center`
# remove item - it's a argument like `center`
new_list[[i]] <- NULL
}
}
}
x <- as.data.frame(new_list, stringsAsFactors = FALSE)
if (any(sapply(x, function(y) !is.numeric(y)))) {
warning("Be sure to first calculate the resistance (or susceptibility) of variables with antimicrobial test results, since PCA works with numeric variables only. Please see Examples in ?pca.")
if (any(vapply(FUN.VALUE = logical(1), x, function(y) !is.numeric(y)))) {
warning_("Be sure to first calculate the resistance (or susceptibility) of variables with antimicrobial test results, since PCA works with numeric variables only. See Examples in ?pca.", call = FALSE)
}
# set column names
@@ -103,21 +107,59 @@ pca <- function(x,
error = function(e) warning("column names could not be set"))
# keep only numeric columns
x <- x[, sapply(x, function(y) is.numeric(y))]
x <- x[, vapply(FUN.VALUE = logical(1), x, function(y) is.numeric(y))]
# bind the data set with the non-numeric columns
x <- cbind(x.bak[, sapply(x.bak, function(y) !is.numeric(y) & !all(is.na(y))), drop = FALSE], x)
x <- cbind(x.bak[, vapply(FUN.VALUE = logical(1), x.bak, function(y) !is.numeric(y) & !all(is.na(y))), drop = FALSE], x)
}
x <- pm_ungroup(x) # would otherwise select the grouping vars
x <- pm_ungroup(x) # would otherwise select the grouping vars
x <- x[rowSums(is.na(x)) == 0, ] # remove columns containing NAs
pca_data <- x[, which(sapply(x, function(x) is.numeric(x)))]
pca_data <- x[, which(vapply(FUN.VALUE = logical(1), x, function(x) is.numeric(x)))]
message(font_blue(paste0("NOTE: Columns selected for PCA: ", paste0(font_bold(colnames(pca_data)), collapse = "/"),
".\n Total observations available: ", nrow(pca_data), ".")))
message_("Columns selected for PCA: ", vector_and(font_bold(colnames(pca_data), collapse = NULL), quotes = TRUE),
". Total observations available: ", nrow(pca_data), ".")
pca_model <- prcomp(pca_data, retx = retx, center = center, scale. = scale., tol = tol, rank. = rank.)
attr(pca_model, "non_numeric_cols") <- x[, sapply(x, function(y) !is.numeric(y) & !all(is.na(y))), drop = FALSE]
if (as.double(R.Version()$major) + (as.double(R.Version()$minor) / 10) < 3.4) {
# stats::prcomp prior to 3.4.0 does not have the 'rank.' argument
pca_model <- prcomp(pca_data, retx = retx, center = center, scale. = scale., tol = tol)
} else {
pca_model <- prcomp(pca_data, retx = retx, center = center, scale. = scale., tol = tol, rank. = rank.)
}
groups <- x[, vapply(FUN.VALUE = logical(1), x, function(y) !is.numeric(y) & !all(is.na(y))), drop = FALSE]
rownames(groups) <- NULL
attr(pca_model, "non_numeric_cols") <- groups
class(pca_model) <- c("pca", class(pca_model))
pca_model
}
#' @method print pca
#' @export
#' @noRd
print.pca <- function(x, ...) {
a <- attributes(x)$non_numeric_cols
if (!is.null(a)) {
print_pca_group(a)
class(x) <- class(x)[class(x) != "pca"]
}
print(x, ...)
}
#' @method summary pca
#' @export
#' @noRd
summary.pca <- function(object, ...) {
a <- attributes(object)$non_numeric_cols
if (!is.null(a)) {
print_pca_group(a)
class(object) <- class(object)[class(object) != "pca"]
}
summary(object, ...)
}
print_pca_group <- function(a) {
grps <- sort(unique(a[, 1, drop = TRUE]))
cat("Groups (n=", length(grps), ", named as '", colnames(a)[1], "'):\n", sep = "")
print(grps)
cat("\n")
}
+15 -16
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,34 +20,34 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Calculate microbial resistance
#' Calculate Microbial Resistance
#'
#' @description These functions can be used to calculate the (co-)resistance or susceptibility of microbial isolates (i.e. percentage of S, SI, I, IR or R). All functions support quasiquotation with pipes, can be used in `summarise()` from the `dplyr` package and also support grouped variables, please see *Examples*.
#' @description These functions can be used to calculate the (co-)resistance or susceptibility of microbial isolates (i.e. percentage of S, SI, I, IR or R). All functions support quasiquotation with pipes, can be used in `summarise()` from the `dplyr` package and also support grouped variables, see *Examples*.
#'
#' [resistance()] should be used to calculate resistance, [susceptibility()] should be used to calculate susceptibility.\cr
#' @inheritSection lifecycle Stable lifecycle
#' @param ... one or more vectors (or columns) with antibiotic interpretations. They will be transformed internally with [as.rsi()] if needed. Use multiple columns to calculate (the lack of) co-resistance: the probability where one of two drugs have a resistant or susceptible result. See Examples.
#' @param minimum the minimum allowed number of available (tested) isolates. Any isolate count lower than `minimum` will return `NA` with a warning. The default number of `30` isolates is advised by the Clinical and Laboratory Standards Institute (CLSI) as best practice, see Source.
#' @inheritSection lifecycle Stable Lifecycle
#' @param ... one or more vectors (or columns) with antibiotic interpretations. They will be transformed internally with [as.rsi()] if needed. Use multiple columns to calculate (the lack of) co-resistance: the probability where one of two drugs have a resistant or susceptible result. See *Examples*.
#' @param minimum the minimum allowed number of available (tested) isolates. Any isolate count lower than `minimum` will return `NA` with a warning. The default number of `30` isolates is advised by the Clinical and Laboratory Standards Institute (CLSI) as best practice, see *Source*.
#' @param as_percent a logical to indicate whether the output must be returned as a hundred fold with % sign (a character). A value of `0.123456` will then be returned as `"12.3%"`.
#' @param only_all_tested (for combination therapies, i.e. using more than one variable for `...`): a logical to indicate that isolates must be tested for all antibiotics, see section *Combination therapy* below
#' @param only_all_tested (for combination therapies, i.e. using more than one variable for `...`): a logical to indicate that isolates must be tested for all antibiotics, see section *Combination Therapy* below
#' @param data a [data.frame] containing columns with class [`rsi`] (see [as.rsi()])
#' @param translate_ab a column name of the [antibiotics] data set to translate the antibiotic abbreviations to, using [ab_property()]. Use a value
#' @param translate_ab a column name of the [antibiotics] data set to translate the antibiotic abbreviations to, using [ab_property()]
#' @inheritParams ab_property
#' @param combine_SI a logical to indicate whether all values of S and I must be merged into one, so the output only consists of S+I vs. R (susceptible vs. resistant). This used to be the parameter `combine_IR`, but this now follows the redefinition by EUCAST about the interpretion of I (increased exposure) in 2019, see section 'Interpretation of S, I and R' below. Default is `TRUE`.
#' @param combine_IR a logical to indicate whether all values of I and R must be merged into one, so the output only consists of S vs. I+R (susceptible vs. non-susceptible). This is outdated, see parameter `combine_SI`.
#' @param combine_SI a logical to indicate whether all values of S and I must be merged into one, so the output only consists of S+I vs. R (susceptible vs. resistant). This used to be the argument `combine_IR`, but this now follows the redefinition by EUCAST about the interpretation of I (increased exposure) in 2019, see section 'Interpretation of S, I and R' below. Default is `TRUE`.
#' @param combine_IR a logical to indicate whether all values of I and R must be merged into one, so the output only consists of S vs. I+R (susceptible vs. non-susceptible). This is outdated, see argument `combine_SI`.
#' @inheritSection as.rsi Interpretation of R and S/I
#' @details
#' The function [resistance()] is equal to the function [proportion_R()]. The function [susceptibility()] is equal to the function [proportion_SI()].
#'
#' **Remember that you should filter your table to let it contain only first isolates!** This is needed to exclude duplicates and to reduce selection bias. Use [first_isolate()] to determine them in your data set.
#'
#' These functions are not meant to count isolates, but to calculate the proportion of resistance/susceptibility. Use the [`count()`][AMR::count()] functions to count isolates. The function [susceptibility()] is essentially equal to `count_susceptible() / count_all()`. *Low counts can influence the outcome - the `proportion` functions may camouflage this, since they only return the proportion (albeit being dependent on the `minimum` parameter).*
#' These functions are not meant to count isolates, but to calculate the proportion of resistance/susceptibility. Use the [`count()`][AMR::count()] functions to count isolates. The function [susceptibility()] is essentially equal to `count_susceptible() / count_all()`. *Low counts can influence the outcome - the `proportion` functions may camouflage this, since they only return the proportion (albeit being dependent on the `minimum` argument).*
#'
#' The function [proportion_df()] takes any variable from `data` that has an [`rsi`] class (created with [as.rsi()]) and calculates the proportions R, I and S. It also supports grouped variables. The function [rsi_df()] works exactly like [proportion_df()], but adds the number of isolates.
#' @section Combination therapy:
#' @section Combination Therapy:
#' When using more than one variable for `...` (= combination therapy), use `only_all_tested` to only count isolates that are tested for all antibiotics/variables that you test them for. See this example for two antibiotics, Drug A and Drug B, about how [susceptibility()] works to calculate the %SI:
#'
#' ```
@@ -88,7 +88,7 @@
#' @aliases portion
#' @name proportion
#' @export
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' # example_isolates is a data set available in the AMR package.
#' ?example_isolates
@@ -266,7 +266,6 @@ proportion_df <- function(data,
as_percent = FALSE,
combine_SI = TRUE,
combine_IR = FALSE) {
rsi_calc_df(type = "proportion",
data = data,
translate_ab = translate_ab,
+132
View File
@@ -0,0 +1,132 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
# GNU General Public License version 2.0 (GNU GPL-2), as published by #
# the Free Software Foundation. #
# We created this package for both routine data analysis and academic #
# research and it was publicly released in the hope that it will be #
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Random MIC Values/Disk Zones/RSI Generation
#'
#' These functions can be used for generating random MIC values and disk diffusion diameters, for AMR data analysis practice.
#' @inheritSection lifecycle Maturing Lifecycle
#' @param size desired size of the returned vector
#' @param mo any character that can be coerced to a valid microorganism code with [as.mo()]
#' @param ab any character that can be coerced to a valid antimicrobial agent code with [as.ab()]
#' @param prob_RSI a vector of length 3: the probabilities for R (1st value), S (2nd value) and I (3rd value)
#' @param ... extension for future versions, not used at the moment
#' @details The base R function [sample()] is used for generating values.
#'
#' Generated values are based on the latest EUCAST guideline implemented in the [rsi_translation] data set. To create specific generated values per bug or drug, set the `mo` and/or `ab` argument.
#' @return class `<mic>` for [random_mic()] (see [as.mic()]) and class `<disk>` for [random_disk()] (see [as.disk()])
#' @name random
#' @rdname random
#' @export
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' random_mic(100)
#' random_disk(100)
#' random_rsi(100)
#'
#' \donttest{
#' # make the random generation more realistic by setting a bug and/or drug:
#' random_mic(100, "Klebsiella pneumoniae") # range 0.0625-64
#' random_mic(100, "Klebsiella pneumoniae", "meropenem") # range 0.0625-16
#' random_mic(100, "Streptococcus pneumoniae", "meropenem") # range 0.0625-4
#'
#' random_disk(100, "Klebsiella pneumoniae") # range 11-50
#' random_disk(100, "Klebsiella pneumoniae", "ampicillin") # range 6-14
#' random_disk(100, "Streptococcus pneumoniae", "ampicillin") # range 16-22
#' }
random_mic <- function(size, mo = NULL, ab = NULL, ...) {
random_exec("MIC", size = size, mo = mo, ab = ab)
}
#' @rdname random
#' @export
random_disk <- function(size, mo = NULL, ab = NULL, ...) {
random_exec("DISK", size = size, mo = mo, ab = ab)
}
#' @rdname random
#' @export
random_rsi <- function(size, prob_RSI = c(0.33, 0.33, 0.33), ...) {
sample(as.rsi(c("R", "S", "I")), size = size, replace = TRUE, prob = prob_RSI)
}
random_exec <- function(type, size, mo = NULL, ab = NULL) {
df <- rsi_translation %pm>%
pm_filter(guideline %like% "EUCAST") %pm>%
pm_arrange(pm_desc(guideline)) %pm>%
subset(guideline == max(guideline) &
method == type)
if (!is.null(mo)) {
mo_coerced <- as.mo(mo)
mo_include <- c(mo_coerced,
as.mo(mo_genus(mo_coerced)),
as.mo(mo_family(mo_coerced)),
as.mo(mo_order(mo_coerced)))
df_new <- df %pm>%
subset(mo %in% mo_include)
if (nrow(df_new) > 0) {
df <- df_new
} else {
warning_("No rows found that match mo '", mo, "', ignoring argument `mo`", call = FALSE)
}
}
if (!is.null(ab)) {
ab_coerced <- as.ab(ab)
df_new <- df %pm>%
subset(ab %in% ab_coerced)
if (nrow(df_new) > 0) {
df <- df_new
} else {
warning_("No rows found that match ab '", ab, "', ignoring argument `ab`", call = FALSE)
}
}
if (type == "MIC") {
# all valid MIC levels
valid_range <- as.mic(levels(as.mic(1)))
set_range_max <- max(df$breakpoint_R)
if (log(set_range_max, 2) %% 1 == 0) {
# return powers of 2
valid_range <- unique(as.double(valid_range))
# add one higher MIC level to set_range_max
set_range_max <- 2 ^ (log(set_range_max, 2) + 1)
set_range <- as.mic(valid_range[log(valid_range, 2) %% 1 == 0 & valid_range <= set_range_max])
} else {
# no power of 2, return factors of 2 to left and right side
valid_mics <- suppressWarnings(as.mic(set_range_max / (2 ^ c(-3:3))))
set_range <- valid_mics[!is.na(valid_mics)]
}
return(as.mic(sample(set_range, size = size, replace = TRUE)))
} else if (type == "DISK") {
set_range <- seq(from = as.integer(min(df$breakpoint_R)),
to = as.integer(max(df$breakpoint_S)),
by = 1)
out <- sample(set_range, size = size, replace = TRUE)
out[out < 6] <- sample(c(6:10), length(out[out < 6]), replace = TRUE)
out[out > 50] <- sample(c(40:50), length(out[out > 50]), replace = TRUE)
return(as.disk(out))
}
}
+35 -22
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,30 +20,30 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Predict antimicrobial resistance
#'
#' Create a prediction model to predict antimicrobial resistance for the next years on statistical solid ground. Standard errors (SE) will be returned as columns `se_min` and `se_max`. See *Examples* for a real live example.
#' @inheritSection lifecycle Maturing lifecycle
#' @inheritSection lifecycle Maturing Lifecycle
#' @param col_ab column name of `x` containing antimicrobial interpretations (`"R"`, `"I"` and `"S"`)
#' @param col_date column name of the date, will be used to calculate years if this column doesn't consist of years already, defaults to the first column of with a date class
#' @param year_min lowest year to use in the prediction model, dafaults to the lowest year in `col_date`
#' @param year_max highest year to use in the prediction model, defaults to 10 years after today
#' @param year_every unit of sequence between lowest year found in the data and `year_max`
#' @param minimum minimal amount of available isolates per year to include. Years containing less observations will be estimated by the model.
#' @param model the statistical model of choice. This could be a generalised linear regression model with binomial distribution (i.e. using `glm(..., family = binomial)``, assuming that a period of zero resistance was followed by a period of increasing resistance leading slowly to more and more resistance. See Details for all valid options.
#' @param I_as_S a logical to indicate whether values `I` should be treated as `S` (will otherwise be treated as `R`). The default, `TRUE`, follows the redefinition by EUCAST about the interpretion of I (increased exposure) in 2019, see section *Interpretation of S, I and R* below.
#' @param model the statistical model of choice. This could be a generalised linear regression model with binomial distribution (i.e. using `glm(..., family = binomial)``, assuming that a period of zero resistance was followed by a period of increasing resistance leading slowly to more and more resistance. See *Details* for all valid options.
#' @param I_as_S a logical to indicate whether values `"I"` should be treated as `"S"` (will otherwise be treated as `"R"`). The default, `TRUE`, follows the redefinition by EUCAST about the interpretation of I (increased exposure) in 2019, see section *Interpretation of S, I and R* below.
#' @param preserve_measurements a logical to indicate whether predictions of years that are actually available in the data should be overwritten by the original data. The standard errors of those years will be `NA`.
#' @param info a logical to indicate whether textual analysis should be printed with the name and [summary()] of the statistical model.
#' @param main title of the plot
#' @param ribbon a logical to indicate whether a ribbon should be shown (default) or error bars
#' @param ... parameters passed on to functions
#' @param ... arguments passed on to functions
#' @inheritSection as.rsi Interpretation of R and S/I
#' @inheritParams first_isolate
#' @inheritParams graphics::plot
#' @details Valid options for the statistical model (parameter `model`) are:
#' @details Valid options for the statistical model (argument `model`) are:
#' - `"binomial"` or `"binom"` or `"logit"`: a generalised linear regression model with binomial distribution
#' - `"loglin"` or `"poisson"`: a generalised log-linear regression model with poisson distribution
#' - `"lin"` or `"linear"`: a linear regression model
@@ -56,14 +56,14 @@
#' - `observed`, the original observed resistant percentages
#' - `estimated`, the estimated resistant percentages, calculated by the model
#'
#' Furthermore, the model itself is available as an attribute: `attributes(x)$model`, please see *Examples*.
#' Furthermore, the model itself is available as an attribute: `attributes(x)$model`, see *Examples*.
#' @seealso The [proportion()] functions to calculate resistance
#'
#' Models: [lm()] [glm()]
#' @rdname resistance_predict
#' @export
#' @importFrom stats predict glm lm
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' x <- resistance_predict(example_isolates,
#' col_ab = "AMX",
@@ -126,22 +126,29 @@ resistance_predict <- function(x,
preserve_measurements = TRUE,
info = interactive(),
...) {
meet_criteria(x, allow_class = "data.frame")
meet_criteria(col_ab, allow_class = "character", has_length = 1, is_in = colnames(x))
meet_criteria(col_date, allow_class = "character", has_length = 1, is_in = colnames(x), allow_NULL = TRUE)
meet_criteria(year_min, allow_class = c("numeric", "integer"), has_length = 1, allow_NULL = TRUE, is_positive = TRUE, is_finite = TRUE)
meet_criteria(year_max, allow_class = c("numeric", "integer"), has_length = 1, allow_NULL = TRUE, is_positive = TRUE, is_finite = TRUE)
meet_criteria(year_every, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(minimum, allow_class = c("numeric", "integer"), has_length = 1, is_finite = TRUE)
meet_criteria(model, allow_class = c("character", "function"), has_length = 1, allow_NULL = TRUE)
meet_criteria(I_as_S, allow_class = "logical", has_length = 1)
meet_criteria(preserve_measurements, allow_class = "logical", has_length = 1)
meet_criteria(info, allow_class = "logical", has_length = 1)
stop_ifnot(is.data.frame(x), "`x` must be a data.frame")
stop_if(any(dim(x) == 0), "`x` must contain rows and columns")
stop_if(is.null(model), 'choose a regression model with the `model` parameter, e.g. resistance_predict(..., model = "binomial")')
stop_ifnot(col_ab %in% colnames(x),
"column `", col_ab, "` not found")
stop_if(is.null(model), 'choose a regression model with the `model` argument, e.g. resistance_predict(..., model = "binomial")')
dots <- unlist(list(...))
if (length(dots) != 0) {
# backwards compatibility with old parameters
dots.names <- dots %pm>% names()
# backwards compatibility with old arguments
dots.names <- names(dots)
if ("tbl" %in% dots.names) {
x <- dots[which(dots.names == "tbl")]
}
if ("I_as_R" %in% dots.names) {
warning("`I_as_R is deprecated - use I_as_S instead.", call. = FALSE)
warning_("`I_as_R is deprecated - use I_as_S instead.", call = FALSE)
}
}
@@ -151,7 +158,7 @@ resistance_predict <- function(x,
stop_if(is.null(col_date), "`col_date` must be set")
}
stop_ifnot(col_date %in% colnames(x),
"column `", col_date, "` not found")
"column '", col_date, "' not found")
# no grouped tibbles
x <- as.data.frame(x, stringsAsFactors = FALSE)
@@ -179,12 +186,15 @@ resistance_predict <- function(x,
# remove rows with NAs
df <- subset(df, !is.na(df[, col_ab, drop = TRUE]))
df$year <- year(df[, col_date, drop = TRUE])
df <- as.data.frame(rbind(table(df[, c("year", col_ab)])), stringsAsFactors = FALSE)
df <- as.data.frame(rbind(table(df[, c("year", col_ab)])),
stringsAsFactors = FALSE)
df$year <- as.integer(rownames(df))
rownames(df) <- NULL
df <- subset(df, sum(df$R + df$S, na.rm = TRUE) >= minimum)
# nolint start
df_matrix <- as.matrix(df[, c("R", "S"), drop = FALSE])
# nolint end
stop_if(NROW(df) == 0, "there are no observations")
@@ -300,6 +310,7 @@ rsi_predict <- resistance_predict
#' @rdname resistance_predict
plot.resistance_predict <- function(x, main = paste("Resistance Prediction of", x_name), ...) {
x_name <- paste0(ab_name(attributes(x)$ab), " (", attributes(x)$ab, ")")
meet_criteria(main, allow_class = "character", has_length = 1)
if (attributes(x)$I_as_S == TRUE) {
ylab <- "%R"
@@ -342,11 +353,13 @@ ggplot_rsi_predict <- function(x,
main = paste("Resistance Prediction of", x_name),
ribbon = TRUE,
...) {
x_name <- paste0(ab_name(attributes(x)$ab), " (", attributes(x)$ab, ")")
meet_criteria(main, allow_class = "character", has_length = 1)
meet_criteria(ribbon, allow_class = "logical", has_length = 1)
stop_ifnot_installed("ggplot2")
stop_ifnot(inherits(x, "resistance_predict"), "`x` must be a resistance prediction model created with resistance_predict()")
x_name <- paste0(ab_name(attributes(x)$ab), " (", attributes(x)$ab, ")")
if (attributes(x)$I_as_S == TRUE) {
ylab <- "%R"
+390 -188
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,65 +20,68 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Interpret MIC and disk values, or clean raw R/SI data
#' Interpret MIC and Disk Values, or Clean Raw R/SI Data
#'
#' Interpret minimum inhibitory concentration (MIC) values and disk diffusion diameters according to EUCAST or CLSI, or clean up existing R/SI values. This transforms the input to a new class [`rsi`], which is an ordered factor with levels `S < I < R`. Values that cannot be interpreted will be returned as `NA` with a warning.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @rdname as.rsi
#' @param x vector of values (for class [`mic`]: an MIC value in mg/L, for class [`disk`]: a disk diffusion radius in millimetres)
#' @param mo any (vector of) text that can be coerced to a valid microorganism code with [as.mo()], will be determined automatically if the `dplyr` package is installed
#' @param mo any (vector of) text that can be coerced to a valid microorganism code with [as.mo()], can be left empty to determine it automatically
#' @param ab any (vector of) text that can be coerced to a valid antimicrobial code with [as.ab()]
#' @param uti (Urinary Tract Infection) A vector with [logical]s (`TRUE` or `FALSE`) to specify whether a UTI specific interpretation from the guideline should be chosen. For using [as.rsi()] on a [data.frame], this can also be a column containing [logical]s or when left blank, the data set will be search for a 'specimen' and rows containing 'urin' in that column will be regarded isolates from a UTI. See *Examples*.
#' @param uti (Urinary Tract Infection) A vector with [logical]s (`TRUE` or `FALSE`) to specify whether a UTI specific interpretation from the guideline should be chosen. For using [as.rsi()] on a [data.frame], this can also be a column containing [logical]s or when left blank, the data set will be searched for a 'specimen' and rows containing 'urin' (such as 'urine', 'urina') in that column will be regarded isolates from a UTI. See *Examples*.
#' @inheritParams first_isolate
#' @param guideline defaults to the latest included EUCAST guideline, see Details for all options
#' @param guideline defaults to the latest included EUCAST guideline, see *Details* for all options
#' @param conserve_capped_values a logical to indicate that MIC values starting with `">"` (but not `">="`) must always return "R" , and that MIC values starting with `"<"` (but not `"<="`) must always return "S"
#' @param add_intrinsic_resistance *(only useful when using a EUCAST guideline)* a logical to indicate whether intrinsic antibiotic resistance must also be considered for applicable bug-drug combinations, meaning that e.g. ampicillin will always return "R" in *Klebsiella* species. Determination is based on the [intrinsic_resistant] data set, that itself is based on 'EUCAST Expert Rules, Intrinsic Resistance and Exceptional Phenotypes', version `r EUCAST_VERSION_EXPERT_RULES`.
#' @param threshold maximum fraction of invalid antimicrobial interpretations of `x`, please see *Examples*
#' @param ... for using on a [data.frame]: names of columns to apply [as.rsi()] on (supports tidy selection like `AMX:VAN`). Otherwise: parameters passed on to methods.
#' @param add_intrinsic_resistance *(only useful when using a EUCAST guideline)* a logical to indicate whether intrinsic antibiotic resistance must also be considered for applicable bug-drug combinations, meaning that e.g. ampicillin will always return "R" in *Klebsiella* species. Determination is based on the [intrinsic_resistant] data set, that itself is based on `r format_eucast_version_nr(3.2)`.
#' @param reference_data a [data.frame] to be used for interpretation, which defaults to the [rsi_translation] data set. Changing this argument allows for using own interpretation guidelines. This argument must contain a data set that is equal in structure to the [rsi_translation] data set (same column names and column types). Please note that the `guideline` argument will be ignored when `reference_data` is manually set.
#' @param threshold maximum fraction of invalid antimicrobial interpretations of `x`, see *Examples*
#' @param ... for using on a [data.frame]: names of columns to apply [as.rsi()] on (supports tidy selection like `AMX:VAN`). Otherwise: arguments passed on to methods.
#' @details
#' ## How it works
#' ## How it Works
#'
#' The [as.rsi()] function works in four ways:
#'
#' 1. For **cleaning raw / untransformed data**. The data will be cleaned to only contain values S, I and R and will try its best to determine this with some intelligence. For example, mixed values with R/SI interpretations and MIC values such as `"<0.25; S"` will be coerced to `"S"`. Combined interpretations for multiple test methods (as seen in laboratory records) such as `"S; S"` will be coerced to `"S"`, but a value like `"S; I"` will return `NA` with a warning that the input is unclear.
#'
#' 2. For **interpreting minimum inhibitory concentration (MIC) values** according to EUCAST or CLSI. You must clean your MIC values first using [as.mic()], that also gives your columns the new data class [`mic`]. Also, be sure to have a column with microorganism names or codes. It will be found automatically, but can be set manually using the `mo` parameter.
#' 2. For **interpreting minimum inhibitory concentration (MIC) values** according to EUCAST or CLSI. You must clean your MIC values first using [as.mic()], that also gives your columns the new data class [`mic`]. Also, be sure to have a column with microorganism names or codes. It will be found automatically, but can be set manually using the `mo` argument.
#' * Using `dplyr`, R/SI interpretation can be done very easily with either:
#' ```
#' your_data %>% mutate_if(is.mic, as.rsi) # until dplyr 1.0.0
#' your_data %>% mutate(across(where(is.mic), as.rsi)) # since dplyr 1.0.0
#' your_data %>% mutate_if(is.mic, as.rsi) # until dplyr 1.0.0
#' your_data %>% mutate(across((is.mic), as.rsi)) # since dplyr 1.0.0
#' ```
#' * Operators like "<=" will be stripped before interpretation. When using `conserve_capped_values = TRUE`, an MIC value of e.g. ">2" will always return "R", even if the breakpoint according to the chosen guideline is ">=4". This is to prevent that capped values from raw laboratory data would not be treated conservatively. The default behaviour (`conserve_capped_values = FALSE`) considers ">2" to be lower than ">=4" and might in this case return "S" or "I".
#'
#' 3. For **interpreting disk diffusion diameters** according to EUCAST or CLSI. You must clean your disk zones first using [as.disk()], that also gives your columns the new data class [`disk`]. Also, be sure to have a column with microorganism names or codes. It will be found automatically, but can be set manually using the `mo` parameter.
#' 3. For **interpreting disk diffusion diameters** according to EUCAST or CLSI. You must clean your disk zones first using [as.disk()], that also gives your columns the new data class [`disk`]. Also, be sure to have a column with microorganism names or codes. It will be found automatically, but can be set manually using the `mo` argument.
#' * Using `dplyr`, R/SI interpretation can be done very easily with either:
#' ```
#' your_data %>% mutate_if(is.disk, as.rsi) # until dplyr 1.0.0
#' your_data %>% mutate(across(where(is.disk), as.rsi)) # since dplyr 1.0.0
#' your_data %>% mutate_if(is.disk, as.rsi) # until dplyr 1.0.0
#' your_data %>% mutate(across((is.disk), as.rsi)) # since dplyr 1.0.0
#' ```
#'
#' 4. For **interpreting a complete data set**, with automatic determination of MIC values, disk diffusion diameters, microorganism names or codes, and antimicrobial test results. This is done very simply by running `as.rsi(data)`.
#'
#' ## Supported guidelines
#' ## Supported Guidelines
#'
#' For interpreting MIC values as well as disk diffusion diameters, supported guidelines to be used as input for the `guideline` parameter are: `r paste0('"', sort(unique(AMR::rsi_translation$guideline)), '"', collapse = ", ")`.
#' For interpreting MIC values as well as disk diffusion diameters, supported guidelines to be used as input for the `guideline` argument are: `r vector_and(AMR::rsi_translation$guideline, quotes = TRUE, reverse = TRUE)`.
#'
#' Simply using `"CLSI"` or `"EUCAST"` as input will automatically select the latest version of that guideline.
#' Simply using `"CLSI"` or `"EUCAST"` as input will automatically select the latest version of that guideline. You can set your own data set using the `reference_data` argument. The `guideline` argument will then be ignored.
#'
#' ## After interpretation
#' ## After Interpretation
#'
#' After using [as.rsi()], you can use the [eucast_rules()] defined by EUCAST to (1) apply inferred susceptibility and resistance based on results of other antimicrobials and (2) apply intrinsic resistance based on taxonomic properties of a microorganism.
#'
#' ## Machine readable interpretation guidelines
#' ## Machine-Readable Interpretation Guidelines
#'
#' The repository of this package [contains a machine readable version](https://github.com/msberends/AMR/blob/master/data-raw/rsi_translation.txt) of all guidelines. This is a CSV file consisting of `r format(nrow(AMR::rsi_translation), big.mark = ",")` rows and `r ncol(AMR::rsi_translation)` columns. This file is machine readable, since it contains one row for every unique combination of the test method (MIC or disk diffusion), the antimicrobial agent and the microorganism. **This allows for easy implementation of these rules in laboratory information systems (LIS)**. Note that it only contains interpretation guidelines for humans - interpretation guidelines from CLSI for animals were removed.
#' The repository of this package [contains a machine-readable version](https://github.com/msberends/AMR/blob/master/data-raw/rsi_translation.txt) of all guidelines. This is a CSV file consisting of `r format(nrow(AMR::rsi_translation), big.mark = ",")` rows and `r ncol(AMR::rsi_translation)` columns. This file is machine-readable, since it contains one row for every unique combination of the test method (MIC or disk diffusion), the antimicrobial agent and the microorganism. **This allows for easy implementation of these rules in laboratory information systems (LIS)**. Note that it only contains interpretation guidelines for humans - interpretation guidelines from CLSI for animals were removed.
#'
#' ## Other
#'
#' The function [is.rsi()] detects if the input contains class `<rsi>`. If the input is a data.frame, it iterates over all columns and returns a logical vector.
#'
#' The function [is.rsi.eligible()] returns `TRUE` when a columns contains at most 5% invalid antimicrobial interpretations (not S and/or I and/or R), and `FALSE` otherwise. The threshold of 5% can be set with the `threshold` parameter.
#' The function [is.rsi.eligible()] returns `TRUE` when a columns contains at most 5% invalid antimicrobial interpretations (not S and/or I and/or R), and `FALSE` otherwise. The threshold of 5% can be set with the `threshold` argument. If the input is a data.frame, it iterates over all columns and returns a logical vector.
#' @section Interpretation of R and S/I:
#' In 2019, the European Committee on Antimicrobial Susceptibility Testing (EUCAST) has decided to change the definitions of susceptibility testing categories R and S/I as shown below (<https://www.eucast.org/newsiandr/>).
#'
@@ -90,29 +93,30 @@
#' A microorganism is categorised as *Susceptible, Increased exposure* when there is a high likelihood of therapeutic success because exposure to the agent is increased by adjusting the dosing regimen or by its concentration at the site of infection.
#'
#' This AMR package honours this new insight. Use [susceptibility()] (equal to [proportion_SI()]) to determine antimicrobial susceptibility and [count_susceptible()] (equal to [count_SI()]) to count susceptible isolates.
#' @return Ordered [factor] with new class [`rsi`]
#' @return Ordered factor with new class `<rsi>`
#' @aliases rsi
#' @export
#' @seealso [as.mic()], [as.disk()], [as.mo()]
#' @inheritSection AMR Reference data publicly available
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Reference Data Publicly Available
#' @inheritSection AMR Read more on Our Website!
#' @examples
#' summary(example_isolates) # see all R/SI results at a glance
#'
#' if (require("skimr")) {
#' # support for skim() too:
#' # class <rsi> supported in skim() too:
#' skim(example_isolates)
#' }
#'
#' # For INTERPRETING disk diffusion and MIC values -----------------------
#'
#' # a whole data set, even with combined MIC values and disk zones
#' df <- data.frame(microorganism = "E. coli",
#' df <- data.frame(microorganism = "Escherichia coli",
#' AMP = as.mic(8),
#' CIP = as.mic(0.256),
#' GEN = as.disk(18),
#' TOB = as.disk(16),
#' NIT = as.mic(32))
#' NIT = as.mic(32),
#' ERY = "R")
#' as.rsi(df)
#'
#' # for single values
@@ -131,12 +135,12 @@
#' if (require("dplyr")) {
#' df %>% mutate_if(is.mic, as.rsi)
#' df %>% mutate_if(function(x) is.mic(x) | is.disk(x), as.rsi)
#' df %>% mutate(across(where(is.mic), as.rsi))
#' df %>% mutate(across((is.mic), as.rsi))
#' df %>% mutate_at(vars(AMP:TOB), as.rsi)
#' df %>% mutate(across(AMP:TOB, as.rsi))
#'
#' df %>%
#' mutate_at(vars(AMP:TOB), as.rsi, mo = "E. coli")
#' mutate_at(vars(AMP:TOB), as.rsi, mo = .$microorganism)
#'
#' # to include information about urinary tract infections (UTI)
#' data.frame(mo = "E. coli",
@@ -177,7 +181,7 @@
#'
#' # note: from dplyr 1.0.0 on, this will be:
#' # example_isolates %>%
#' # mutate(across(where(is.rsi.eligible), as.rsi))
#' # mutate(across((is.rsi.eligible), as.rsi))
#' }
#' }
as.rsi <- function(x, ...) {
@@ -187,30 +191,60 @@ as.rsi <- function(x, ...) {
#' @rdname as.rsi
#' @export
is.rsi <- function(x) {
inherits(x, "rsi")
if (inherits(x, "data.frame")) {
unname(vapply(FUN.VALUE = logical(1), x, is.rsi))
} else {
inherits(x, "rsi")
}
}
#' @rdname as.rsi
#' @export
is.rsi.eligible <- function(x, threshold = 0.05) {
meet_criteria(threshold, allow_class = "numeric", has_length = 1)
if (inherits(x, "data.frame")) {
# iterate this function over all columns
return(unname(vapply(FUN.VALUE = logical(1), x, is.rsi.eligible)))
}
stop_if(NCOL(x) > 1, "`x` must be a one-dimensional vector.")
if (any(c("logical",
"numeric",
if (any(c("numeric",
"integer",
"mo",
"ab",
"Date",
"POSIXct",
"POSIXt",
"rsi",
"raw",
"hms")
"hms",
"mic",
"disk")
%in% class(x))) {
# no transformation needed
FALSE
return(FALSE)
} else if (all(x %in% c("R", "S", "I", NA)) & !all(is.na(x))) {
return(TRUE)
} else if (!any(c("R", "S", "I") %in% x, na.rm = TRUE) & !all(is.na(x))) {
return(FALSE)
} else {
x <- x[!is.na(x) & !is.null(x) & !identical(x, "")]
x <- x[!is.na(x) & !is.null(x) & x != ""]
if (length(x) == 0) {
# no other values than NA or ""
cur_col <- get_current_column()
if (!is.null(cur_col)) {
ab <- suppressWarnings(as.ab(cur_col, fast_mode = TRUE, info = FALSE))
if (!is.na(ab)) {
# this is a valid antibiotic code
message_("Column '", font_bold(cur_col), "' is as.rsi()-eligible (despite only having empty values), since it seems to be ",
ab_name(ab, language = NULL, tolower = TRUE), " (", ab, ")")
return(TRUE)
}
}
# all values empty and no antibiotic col name - return FALSE
return(FALSE)
}
# transform all values and see if it meets the set threshold
checked <- suppressWarnings(as.rsi(x))
outcome <- sum(is.na(checked)) / length(x)
outcome <= threshold
@@ -220,24 +254,22 @@ is.rsi.eligible <- function(x, threshold = 0.05) {
#' @export
as.rsi.default <- function(x, ...) {
if (is.rsi(x)) {
x
} else if (all(is.na(x)) || identical(levels(x), c("S", "I", "R"))) {
structure(.Data = factor(x, levels = c("S", "I", "R"), ordered = TRUE),
class = c("rsi", "ordered", "factor"))
} else if (inherits(x, "integer") & all(x %in% c(1:3, NA))) {
return(x)
}
if (inherits(x, "integer") & all(x %in% c(1:3, NA))) {
x[x == 1] <- "S"
x[x == 2] <- "I"
x[x == 3] <- "R"
structure(.Data = factor(x, levels = c("S", "I", "R"), ordered = TRUE),
class = c("rsi", "ordered", "factor"))
} else {
} else if (!all(is.na(x)) && !identical(levels(x), c("S", "I", "R"))) {
if (!any(x %like% "(R|S|I)", na.rm = TRUE)) {
# check if they are actually MICs or disks now that the antibiotic name is valid
if (all_valid_mics(x)) {
warning("The input seems to be MIC values. Transform them with as.mic() before running as.rsi() to interpret them.")
warning_("The input seems to be MIC values. Transform them with as.mic() before running as.rsi() to interpret them.")
} else if (all_valid_disks(x)) {
warning("The input seems to be disk diffusion values. Transform them with as.disk() before running as.rsi() to interpret them.")
warning_("The input seems to be disk diffusion values. Transform them with as.disk() before running as.rsi() to interpret them.")
}
}
@@ -269,18 +301,18 @@ as.rsi.default <- function(x, ...) {
if (na_before != na_after) {
list_missing <- x.bak[is.na(x) & !is.na(x.bak) & x.bak != ""] %pm>%
unique() %pm>%
sort()
list_missing <- paste0('"', list_missing, '"', collapse = ", ")
warning(na_after - na_before, " results truncated (",
round(((na_after - na_before) / length(x)) * 100),
"%) that were invalid antimicrobial interpretations: ",
list_missing, call. = FALSE)
sort() %pm>%
vector_and(quotes = TRUE)
warning_(na_after - na_before, " results truncated (",
round(((na_after - na_before) / length(x)) * 100),
"%) that were invalid antimicrobial interpretations: ",
list_missing, call = FALSE)
}
}
structure(.Data = factor(x, levels = c("S", "I", "R"), ordered = TRUE),
class = c("rsi", "ordered", "factor"))
}
set_clean_class(factor(x, levels = c("S", "I", "R"), ordered = TRUE),
new_class = c("rsi", "ordered", "factor"))
}
#' @rdname as.rsi
@@ -292,7 +324,17 @@ as.rsi.mic <- function(x,
uti = FALSE,
conserve_capped_values = FALSE,
add_intrinsic_resistance = FALSE,
reference_data = AMR::rsi_translation,
...) {
meet_criteria(x)
meet_criteria(mo, allow_class = c("mo", "character"), allow_NULL = TRUE)
meet_criteria(ab, allow_class = c("ab", "character"))
meet_criteria(guideline, allow_class = "character", has_length = 1)
meet_criteria(uti, allow_class = "logical", has_length = c(1, length(x)))
meet_criteria(conserve_capped_values, allow_class = "logical", has_length = 1)
meet_criteria(add_intrinsic_resistance, allow_class = "logical", has_length = 1)
meet_criteria(reference_data, allow_class = "data.frame")
check_reference_data(reference_data)
# for dplyr's across()
cur_column_dplyr <- import_fn("cur_column", "dplyr", error_on_fail = FALSE)
@@ -305,30 +347,34 @@ as.rsi.mic <- function(x,
# for auto-determining mo
mo_var_found <- ""
if (is.null(mo)) {
peek_mask_dplyr <- import_fn("peek_mask", "dplyr", error_on_fail = FALSE)
if (!is.null(peek_mask_dplyr)) {
tryCatch({
df <- get_current_data(arg_name = "mo", call = -3) # will return an error if not found
mo <- NULL
try({
df <- as.data.frame(peek_mask_dplyr()$across_cols(), stringsAsFactors = FALSE)
mo <- suppressMessages(search_type_in_df(df, "mo"))
if (!is.null(mo)) {
mo_var_found <- paste0(" based on column `", font_bold(mo), "`")
mo <- df[, mo, drop = TRUE]
}
}, silent = TRUE)
}
if (!is.null(df) && !is.null(mo) && is.data.frame(df)) {
mo_var_found <- paste0(" based on column '", font_bold(mo), "'")
mo <- df[, mo, drop = TRUE]
}
}, error = function(e)
stop_('No information was supplied about the microorganisms (missing argument `mo`). See ?as.rsi.\n\n',
"To transform certain columns with e.g. mutate_at(), use `data %>% mutate_at(vars(...), as.rsi, mo = .$x)`, where x is your column with microorganisms.\n",
"To tranform all disk diffusion zones in a data set, use `data %>% as.rsi()` or data %>% mutate_if(is.disk, as.rsi).", call = FALSE)
)
}
if (is.null(mo)) {
stop_('No information was supplied about the microorganisms (missing parameter "mo"). See ?as.rsi.\n\n',
"To transform certain columns with e.g. mutate_at(), use\n",
"`data %>% mutate_at(vars(...), as.rsi, mo = .$x)`, where x is your column with microorganisms.\n\n",
"To tranform all MIC values in a data set, use `data %>% as.rsi()` or data %>% mutate_if(is.mic, as.rsi).", call = FALSE)
if (length(ab) == 1 && ab %like% "as.mic") {
stop_('No unambiguous name was supplied about the antibiotic (argument `ab`). See ?as.rsi.', call = FALSE)
}
ab_coerced <- suppressWarnings(as.ab(ab))
mo_coerced <- suppressWarnings(as.mo(mo))
guideline_coerced <- get_guideline(guideline)
guideline_coerced <- get_guideline(guideline, reference_data)
if (is.na(ab_coerced)) {
message(font_red(paste0("Returning NAs for unknown drug: `", font_bold(ab), "`. Rename this column to a drug name or code, and check the output with as.ab().")))
message_("Returning NAs for unknown drug: '", font_bold(ab),
"'. Rename this column to a drug name or code, and check the output with `as.ab()`.",
add_fn = font_red,
as_note = FALSE)
return(as.rsi(rep(NA, length(x))))
}
if (length(mo_coerced) == 1) {
@@ -338,11 +384,15 @@ as.rsi.mic <- function(x,
uti <- rep(uti, length(x))
}
message(font_blue(paste0("=> Interpreting MIC values of `", font_bold(ab), "` (",
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE), ")", mo_var_found,
" according to ", font_bold(guideline_coerced), " ... ")),
appendLF = FALSE)
message_("=> Interpreting MIC values of ", ifelse(isTRUE(list(...)$is_data.frame), "column ", ""), "'", font_bold(ab), "' (",
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE), ")", mo_var_found,
" according to ", ifelse(identical(reference_data, AMR::rsi_translation),
font_bold(guideline_coerced),
"manually defined 'reference_data'"),
" ... ",
appendLF = FALSE,
as_note = FALSE)
result <- exec_as.rsi(method = "mic",
x = x,
@@ -351,7 +401,8 @@ as.rsi.mic <- function(x,
guideline = guideline_coerced,
uti = uti,
conserve_capped_values = conserve_capped_values,
add_intrinsic_resistance = add_intrinsic_resistance) # exec_as.rsi will return message(font_blue(" OK."))
add_intrinsic_resistance = add_intrinsic_resistance,
reference_data = reference_data) # exec_as.rsi will return message 'OK'
result
}
@@ -363,7 +414,16 @@ as.rsi.disk <- function(x,
guideline = "EUCAST",
uti = FALSE,
add_intrinsic_resistance = FALSE,
reference_data = AMR::rsi_translation,
...) {
meet_criteria(x)
meet_criteria(mo, allow_class = c("mo", "character"), allow_NULL = TRUE)
meet_criteria(ab, allow_class = c("ab", "character"))
meet_criteria(guideline, allow_class = "character", has_length = 1)
meet_criteria(uti, allow_class = "logical", has_length = c(1, length(x)))
meet_criteria(add_intrinsic_resistance, allow_class = "logical", has_length = 1)
meet_criteria(reference_data, allow_class = "data.frame")
check_reference_data(reference_data)
# for dplyr's across()
cur_column_dplyr <- import_fn("cur_column", "dplyr", error_on_fail = FALSE)
@@ -376,30 +436,34 @@ as.rsi.disk <- function(x,
# for auto-determining mo
mo_var_found <- ""
if (is.null(mo)) {
peek_mask_dplyr <- import_fn("peek_mask", "dplyr", error_on_fail = FALSE)
if (!is.null(peek_mask_dplyr)) {
tryCatch({
df <- get_current_data(arg_name = "mo", call = -3) # will return an error if not found
mo <- NULL
try({
df <- as.data.frame(peek_mask_dplyr()$across_cols(), stringsAsFactors = FALSE)
mo <- suppressMessages(search_type_in_df(df, "mo"))
if (!is.null(mo)) {
mo_var_found <- paste0(" based on column `", font_bold(mo), "`")
mo <- df[, mo, drop = TRUE]
}
}, silent = TRUE)
}
if (!is.null(df) && !is.null(mo) && is.data.frame(df)) {
mo_var_found <- paste0(" based on column '", font_bold(mo), "'")
mo <- df[, mo, drop = TRUE]
}
}, error = function(e)
stop_('No information was supplied about the microorganisms (missing argument `mo`). See ?as.rsi.\n\n',
"To transform certain columns with e.g. mutate_at(), use `data %>% mutate_at(vars(...), as.rsi, mo = .$x)`, where x is your column with microorganisms.\n",
"To tranform all disk diffusion zones in a data set, use `data %>% as.rsi()` or data %>% mutate_if(is.disk, as.rsi).", call = FALSE)
)
}
if (is.null(mo)) {
stop_('No information was supplied about the microorganisms (missing parameter "mo"). See ?as.rsi.\n\n',
"To transform certain columns with e.g. mutate_at(), use\n",
"`data %>% mutate_at(vars(...), as.rsi, mo = .$x)`, where x is your column with microorganisms.\n\n",
"To tranform all disk diffusion zones in a data set, use `data %>% as.rsi()` or data %>% mutate_if(is.disk, as.rsi).", call = FALSE)
if (length(ab) == 1 && ab %like% "as.disk") {
stop_('No unambiguous name was supplied about the antibiotic (argument `ab`). See ?as.rsi.', call = FALSE)
}
ab_coerced <- suppressWarnings(as.ab(ab))
mo_coerced <- suppressWarnings(as.mo(mo))
guideline_coerced <- get_guideline(guideline)
guideline_coerced <- get_guideline(guideline, reference_data)
if (is.na(ab_coerced)) {
message(font_red(paste0("Returning NAs for unknown drug: `", font_bold(ab), "`. Rename this column to a drug name or code, and check the output with as.ab().")))
message_("Returning NAs for unknown drug: '", font_bold(ab),
"'. Rename this column to a drug name or code, and check the output with `as.ab()`.",
add_fn = font_red,
as_note = FALSE)
return(as.rsi(rep(NA, length(x))))
}
if (length(mo_coerced) == 1) {
@@ -409,10 +473,16 @@ as.rsi.disk <- function(x,
uti <- rep(uti, length(x))
}
message(font_blue(paste0("=> Interpreting disk zones of `", font_bold(ab), "` (",
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE), ") using guideline ", font_bold(guideline_coerced), " ... ")),
appendLF = FALSE)
message_("=> Interpreting disk zones of ", ifelse(isTRUE(list(...)$is_data.frame), "column ", ""), "'", font_bold(ab), "' (",
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE), ")", mo_var_found,
" according to ", ifelse(identical(reference_data, AMR::rsi_translation),
font_bold(guideline_coerced),
"manually defined 'reference_data'"),
" ... ",
appendLF = FALSE,
as_note = FALSE)
result <- exec_as.rsi(method = "disk",
x = x,
mo = mo_coerced,
@@ -420,7 +490,8 @@ as.rsi.disk <- function(x,
guideline = guideline_coerced,
uti = uti,
conserve_capped_values = FALSE,
add_intrinsic_resistance = add_intrinsic_resistance) # exec_as.rsi will return message(font_blue(" OK."))
add_intrinsic_resistance = add_intrinsic_resistance,
reference_data = reference_data) # exec_as.rsi will return message 'OK'
result
}
@@ -432,8 +503,30 @@ as.rsi.data.frame <- function(x,
guideline = "EUCAST",
uti = NULL,
conserve_capped_values = FALSE,
add_intrinsic_resistance = FALSE) {
add_intrinsic_resistance = FALSE,
reference_data = AMR::rsi_translation) {
meet_criteria(x, allow_class = "data.frame") # will also check for dimensions > 0
meet_criteria(col_mo, allow_class = "character", is_in = colnames(x), allow_NULL = TRUE)
meet_criteria(guideline, allow_class = "character", has_length = 1)
meet_criteria(uti, allow_class = c("logical", "character"), allow_NULL = TRUE)
meet_criteria(conserve_capped_values, allow_class = "logical", has_length = 1)
meet_criteria(add_intrinsic_resistance, allow_class = "logical", has_length = 1)
meet_criteria(reference_data, allow_class = "data.frame")
x.bak <- x
for (i in seq_len(ncol(x))) {
# don't keep factors
if (is.factor(x[, i, drop = TRUE])) {
x[, i] <- as.character(x[, i, drop = TRUE])
}
}
# -- MO
col_mo.bak <- col_mo
if (is.null(col_mo)) {
col_mo <- search_type_in_df(x = x, type = "mo", info = FALSE)
}
# -- UTIs
col_uti <- uti
if (is.null(col_uti)) {
@@ -449,6 +542,8 @@ as.rsi.data.frame <- function(x,
}
} else {
# column found, transform to logical
stop_if(length(col_uti) != 1 | !col_uti %in% colnames(x),
"argument `uti` must be a logical vector, of must be a single column name of `x`")
uti <- as.logical(x[, col_uti, drop = TRUE])
}
} else {
@@ -462,104 +557,141 @@ as.rsi.data.frame <- function(x,
} else {
plural <- c("", "s", "a ")
}
message(font_blue(paste0("NOTE: Assuming value", plural[1], " ",
paste(paste0('"', values, '"'), collapse = ", "),
" in column `", font_bold(col_specimen),
"` reflect", plural[2], " ", plural[3], "urinary tract infection", plural[1], ".\n Use `as.rsi(uti = FALSE)` to prevent this.")))
message_("Assuming value", plural[1], " ",
vector_and(values, quotes = TRUE),
" in column '", font_bold(col_specimen),
"' reflect", plural[2], " ", plural[3], "urinary tract infection", plural[1],
".\n Use `as.rsi(uti = FALSE)` to prevent this.")
} else {
# no data about UTI's found
uti <- FALSE
}
}
i <- 0
sel <- colnames(pm_select(x, ...))
ab_cols <- colnames(x)[sapply(x, function(y) {
if (!is.null(col_mo)) {
sel <- sel[sel != col_mo]
}
ab_cols <- colnames(x)[vapply(FUN.VALUE = logical(1), x, function(y) {
i <<- i + 1
check <- is.mic(y) | is.disk(y)
ab <- colnames(x)[i]
if (!is.null(col_mo) && ab == col_mo) {
return(FALSE)
}
if (!is.null(col_uti) && ab == col_uti) {
return(FALSE)
}
if (length(sel) == 0 || (length(sel) > 0 && ab %in% sel)) {
ab_coerced <- suppressWarnings(as.ab(ab))
if (is.na(ab_coerced) || (length(sel) > 0 & !ab %in% sel)) {
# not even a valid AB code
return(FALSE)
} else {
if (!check & all_valid_mics(y)) {
message(font_blue(paste0("NOTE: Assuming column `", ab, "` (",
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE), ") contains MIC values.")))
} else if (!check & all_valid_disks(y)) {
message(font_blue(paste0("NOTE: Assuming column `", ab, "` (",
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE), ") contains disk zones.")))
} else if (!check & !is.rsi(y)) {
message(font_blue(paste0("NOTE: Assuming column `", ab, "` (",
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE), ") must be cleaned to valid R/SI values.")))
}
return(TRUE)
}
} else {
return(FALSE)
}
})]
stop_if(length(ab_cols) == 0,
"no columns with MIC values, disk zones or antibiotic column names found in this data set. Use as.mic() or as.disk() to transform antimicrobial columns.")
# set type per column
types <- character(length(ab_cols))
types[sapply(x[, ab_cols], is.mic)] <- "mic"
types[types == "" & sapply(x[, ab_cols], all_valid_mics)] <- "mic"
types[sapply(x[, ab_cols], is.disk)] <- "disk"
types[types == "" & sapply(x[, ab_cols], all_valid_disks)] <- "disk"
types[types == "" & !sapply(x[, ab_cols], is.rsi)] <- "rsi"
types[vapply(FUN.VALUE = logical(1), x.bak[, ab_cols, drop = FALSE], is.disk)] <- "disk"
types[vapply(FUN.VALUE = logical(1), x.bak[, ab_cols, drop = FALSE], is.mic)] <- "mic"
types[types == "" & vapply(FUN.VALUE = logical(1), x[, ab_cols, drop = FALSE], all_valid_disks)] <- "disk"
types[types == "" & vapply(FUN.VALUE = logical(1), x[, ab_cols, drop = FALSE], all_valid_mics)] <- "mic"
types[types == "" & !vapply(FUN.VALUE = logical(1), x.bak[, ab_cols, drop = FALSE], is.rsi)] <- "rsi"
if (any(types %in% c("mic", "disk"), na.rm = TRUE)) {
# now we need an mo column - try to find columns based on type
if (is.null(col_mo)) {
# now we need an mo column
stop_if(is.null(col_mo), "`col_mo` must be set")
# if not null, we already found it, now find again so a message will show
if (is.null(col_mo.bak)) {
col_mo <- search_type_in_df(x = x, type = "mo")
stop_if(is.null(col_mo), "`col_mo` must be set")
}
}
x_mo <- as.mo(x %pm>% pm_pull(col_mo))
for (i in seq_len(length(ab_cols))) {
if (types[i] == "mic") {
x[, ab_cols[i]] <- as.rsi.mic(x = x %pm>% pm_pull(ab_cols[i]),
mo = x %pm>% pm_pull(col_mo),
ab = ab_cols[i],
guideline = guideline,
uti = uti,
conserve_capped_values = conserve_capped_values)
x[, ab_cols[i]] <- as.rsi(x = x %pm>%
pm_pull(ab_cols[i]) %pm>%
as.character() %pm>%
as.mic(),
mo = x_mo,
ab = ab_cols[i],
guideline = guideline,
uti = uti,
conserve_capped_values = conserve_capped_values,
add_intrinsic_resistance = add_intrinsic_resistance,
reference_data = reference_data,
is_data.frame = TRUE)
} else if (types[i] == "disk") {
x[, ab_cols[i]] <- as.rsi.disk(x = x %pm>% pm_pull(ab_cols[i]),
mo = x %pm>% pm_pull(col_mo),
ab = ab_cols[i],
guideline = guideline,
uti = uti)
x[, ab_cols[i]] <- as.rsi(x = x %pm>%
pm_pull(ab_cols[i]) %pm>%
as.character() %pm>%
as.disk(),
mo = x_mo,
ab = ab_cols[i],
guideline = guideline,
uti = uti,
add_intrinsic_resistance = add_intrinsic_resistance,
reference_data = reference_data,
is_data.frame = TRUE)
} else if (types[i] == "rsi") {
x[, ab_cols[i]] <- as.rsi.default(x = x %pm>% pm_pull(ab_cols[i]))
show_message <- FALSE
ab <- ab_cols[i]
ab_coerced <- suppressWarnings(as.ab(ab))
if (!all(x[, ab_cols[i], drop = TRUE] %in% c("R", "S", "I"), na.rm = TRUE)) {
show_message <- TRUE
# only print message if values are not already clean
message_("=> Cleaning values in column '", font_bold(ab), "' (",
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE), ")... ",
appendLF = FALSE,
as_note = FALSE)
} else if (!is.rsi(x.bak[, ab_cols[i], drop = TRUE])) {
show_message <- TRUE
# only print message if class not already set
message_("=> Assigning class <rsi> to already clean column '", font_bold(ab), "' (",
ifelse(ab_coerced != ab, paste0(ab_coerced, ", "), ""),
ab_name(ab_coerced, tolower = TRUE), ")... ",
appendLF = FALSE,
as_note = FALSE)
}
x[, ab_cols[i]] <- as.rsi.default(x = as.character(x[, ab_cols[i], drop = TRUE]))
if (show_message == TRUE) {
message_(" OK.", add_fn = list(font_green, font_bold), as_note = FALSE)
}
}
}
x
}
get_guideline <- function(guideline) {
get_guideline <- function(guideline, reference_data) {
if (!identical(reference_data, AMR::rsi_translation)) {
return(guideline)
}
guideline_param <- toupper(guideline)
if (guideline_param %in% c("CLSI", "EUCAST")) {
guideline_param <- rev(sort(subset(rsi_translation, guideline %like% guideline_param)$guideline))[1L]
guideline_param <- rev(sort(subset(reference_data, guideline %like% guideline_param)$guideline))[1L]
}
if (!guideline_param %like% " ") {
# like 'EUCAST2020', should be 'EUCAST 2020'
guideline_param <- gsub("([a-z]+)([0-9]+)", "\\1 \\2", guideline_param, ignore.case = TRUE)
}
stop_ifnot(guideline_param %in% rsi_translation$guideline,
stop_ifnot(guideline_param %in% reference_data$guideline,
"invalid guideline: '", guideline,
"'.\nValid guidelines are: ", paste0("'", unique(rsi_translation$guideline), "'", collapse = ", "), call = FALSE)
"'.\nValid guidelines are: ", vector_and(reference_data$guideline, quotes = TRUE, reverse = TRUE), call = FALSE)
guideline_param
}
exec_as.rsi <- function(method,
@@ -569,11 +701,12 @@ exec_as.rsi <- function(method,
guideline,
uti,
conserve_capped_values,
add_intrinsic_resistance) {
add_intrinsic_resistance,
reference_data) {
metadata_mo <- get_mo_failures_uncertainties_renamed()
x_bak <- data.frame(x_mo = paste0(x, mo))
x_bak <- data.frame(x_mo = paste0(x, mo), stringsAsFactors = FALSE)
df <- unique(data.frame(x, mo), stringsAsFactors = FALSE)
x <- df$x
mo <- df$mo
@@ -603,15 +736,23 @@ exec_as.rsi <- function(method,
}
mo_other <- as.mo(rep("UNKNOWN", length(mo)))
guideline_coerced <- get_guideline(guideline)
guideline_coerced <- get_guideline(guideline, reference_data)
if (guideline_coerced != guideline) {
message(font_blue(paste0("Note: Using guideline ", font_bold(guideline_coerced), " as input for `guideline`.")))
if (message_not_thrown_before("as.rsi")) {
message_("Using guideline ", font_bold(guideline_coerced), " as input for `guideline`.")
remember_thrown_message("as.rsi")
}
}
new_rsi <- rep(NA_character_, length(x))
ab_param <- ab
trans <- rsi_translation %pm>%
subset(guideline == guideline_coerced & method == method_param & ab == ab_param)
if (identical(reference_data, AMR::rsi_translation)) {
trans <- reference_data %pm>%
subset(guideline == guideline_coerced & method == method_param & ab == ab_param)
} else {
trans <- reference_data %pm>%
subset(method == method_param & ab == ab_param)
}
trans$lookup <- paste(trans$mo, trans$ab)
lookup_mo <- paste(mo, ab)
@@ -623,22 +764,26 @@ exec_as.rsi <- function(method,
lookup_other <- paste(mo_other, ab)
if (all(trans$uti == TRUE, na.rm = TRUE) & all(uti == FALSE)) {
message(font_red("WARNING."))
warning("Interpretation of ", font_bold(ab_name(ab, tolower = TRUE)), " for some microorganisms is only available for (uncomplicated) urinary tract infections (UTI).\n Use parameter 'uti' to set which isolates are from urine. See ?as.rsi.", call. = FALSE)
message_("WARNING.", add_fn = list(font_yellow, font_bold), as_note = FALSE)
warning_("Introducing NA: interpretation of ", font_bold(ab_name(ab, tolower = TRUE)), " for some microorganisms is only available for (uncomplicated) urinary tract infections (UTI). Use argument `uti` to set which isolates are from urine. See ?as.rsi.", call = FALSE)
warned <- TRUE
}
any_is_intrinsic_resistant <- FALSE
for (i in seq_len(length(x))) {
if (isTRUE(add_intrinsic_resistance)) {
is_intrinsic_r <- paste(mo[i], ab) %in% INTRINSIC_R
any_is_intrinsic_resistant <- any_is_intrinsic_resistant | is_intrinsic_r
if (isTRUE(add_intrinsic_resistance) & is_intrinsic_r) {
if (!guideline_coerced %like% "EUCAST") {
warning("Using 'add_intrinsic_resistance' is only useful when using EUCAST guidelines, since the rules for intrinsic resistance are based on EUCAST.", call. = FALSE)
} else {
get_record <- subset(intrinsic_resistant,
microorganism == mo_name(mo[i], language = NULL) & antibiotic == ab_name(ab, language = NULL))
if (nrow(get_record) > 0) {
new_rsi[i] <- "R"
next
if (message_not_thrown_before("as.rsi2")) {
warning_("Using 'add_intrinsic_resistance' is only useful when using EUCAST guidelines, since the rules for intrinsic resistance are based on EUCAST.", call = FALSE)
remember_thrown_message("as.rsi2")
}
} else {
new_rsi[i] <- "R"
next
}
}
@@ -698,27 +843,43 @@ exec_as.rsi <- function(method,
}
}
if (any_is_intrinsic_resistant & guideline_coerced %like% "EUCAST" & !isTRUE(add_intrinsic_resistance)) {
# found some intrinsic resistance, but was not applied
message_("WARNING.", add_fn = list(font_yellow, font_bold), as_note = FALSE)
if (message_not_thrown_before("as.rsi3")) {
warning_("Found intrinsic resistance in some bug/drug combinations, although it was not applied.\nUse `as.rsi(..., add_intrinsic_resistance = TRUE)` to apply it.", call = FALSE)
remember_thrown_message("as.rsi3")
}
warned <- TRUE
}
new_rsi <- x_bak %pm>%
pm_left_join(data.frame(x_mo = paste0(df$x, df$mo), new_rsi), by = "x_mo") %pm>%
pm_left_join(data.frame(x_mo = paste0(df$x, df$mo), new_rsi,
stringsAsFactors = FALSE),
by = "x_mo") %pm>%
pm_pull(new_rsi)
if (warned == FALSE) {
message(font_green("OK."))
message_(" OK.", add_fn = list(font_green, font_bold), as_note = FALSE)
}
load_mo_failures_uncertainties_renamed(metadata_mo)
structure(.Data = factor(new_rsi, levels = c("S", "I", "R"), ordered = TRUE),
class = c("rsi", "ordered", "factor"))
set_clean_class(factor(new_rsi, levels = c("S", "I", "R"), ordered = TRUE),
new_class = c("rsi", "ordered", "factor"))
}
# will be exported using s3_register() in R/zzz.R
pillar_shaft.rsi <- function(x, ...) {
out <- trimws(format(x))
out[is.na(x)] <- font_grey(" NA")
out[x == "S"] <- font_green_bg(font_white(" S "))
out[x == "I"] <- font_yellow_bg(font_black(" I "))
out[x == "R"] <- font_red_bg(font_white(" R "))
if (has_colour()) {
# colours will anyway not work when has_colour() == FALSE,
# but then the indentation should also not be applied
out[is.na(x)] <- font_grey(" NA")
out[x == "R"] <- font_rsi_R_bg(font_black(" R "))
out[x == "S"] <- font_rsi_S_bg(font_black(" S "))
out[x == "I"] <- font_rsi_I_bg(font_black(" I "))
}
create_pillar_column(out, align = "left", width = 5)
}
@@ -731,20 +892,32 @@ type_sum.rsi <- function(x, ...) {
freq.rsi <- function(x, ...) {
x_name <- deparse(substitute(x))
x_name <- gsub(".*[$]", "", x_name)
if (x_name %in% c("x", ".")) {
# try again going through system calls
x_name <- stats::na.omit(vapply(FUN.VALUE = character(1),
sys.calls(),
function(call) {
call_txt <- as.character(call)
ifelse(call_txt[1] %like% "freq$", call_txt[length(call_txt)], character(0))
}))[1L]
}
ab <- suppressMessages(suppressWarnings(as.ab(x_name)))
freq.default <- import_fn("freq.default", "cleaner", error_on_fail = FALSE)
digits <- list(...)$digits
if (is.null(digits)) {
digits <- 2
}
if (!is.na(ab)) {
freq.default(x = x, ...,
.add_header = list(Drug = paste0(ab_name(ab, language = NULL), " (", ab, ", ", ab_atc(ab), ")"),
`Drug group` = ab_group(ab, language = NULL),
`%SI` = percentage(susceptibility(x, minimum = 0, as_percent = FALSE), digits = digits)))
cleaner::freq.default(x = x, ...,
.add_header = list(
Drug = paste0(ab_name(ab, language = NULL), " (", ab, ", ", ab_atc(ab), ")"),
`Drug group` = ab_group(ab, language = NULL),
`%SI` = percentage(susceptibility(x, minimum = 0, as_percent = FALSE),
digits = digits)))
} else {
freq.default(x = x, ...,
.add_header = list(`%SI` = percentage(susceptibility(x, minimum = 0, as_percent = FALSE), digits = digits)))
cleaner::freq.default(x = x, ...,
.add_header = list(
`%SI` = percentage(susceptibility(x, minimum = 0, as_percent = FALSE),
digits = digits)))
}
}
@@ -767,8 +940,8 @@ get_skimmers.rsi <- function(column) {
if (is.null(vars) | is.null(i)) {
NA_character_
} else {
lengths <- sapply(vars, length)
when_starts_rsi <- which(names(sapply(vars, length)) == "rsi")
lengths <- vapply(FUN.VALUE = double(1), vars, length)
when_starts_rsi <- which(names(vapply(FUN.VALUE = double(1), vars, length)) == "rsi")
offset <- sum(lengths[c(1:when_starts_rsi - 1)])
var <- vars$rsi[i - offset]
if (!isFALSE(var == "data")) {
@@ -779,8 +952,7 @@ get_skimmers.rsi <- function(column) {
}
}
sfl <- import_fn("sfl", "skimr", error_on_fail = FALSE)
sfl(
skimr::sfl(
skim_type = "rsi",
ab_name = name_call,
count_R = count_R,
@@ -803,7 +975,7 @@ print.rsi <- function(x, ...) {
#' @method droplevels rsi
#' @export
#' @noRd
droplevels.rsi <- function(x, exclude = if (anyNA(levels(x))) NULL else NA, ...) {
droplevels.rsi <- function(x, exclude = if (any(is.na(levels(x)))) NULL else NA, ...) {
x <- droplevels.factor(x, exclude = exclude, ...)
class(x) <- c("rsi", "ordered", "factor")
x
@@ -850,18 +1022,28 @@ plot.rsi <- function(x,
main = paste("Resistance Overview of", deparse(substitute(x))),
axes = FALSE,
...) {
meet_criteria(lwd, allow_class = c("numeric", "integer"), has_length = 1, is_positive = TRUE, is_finite = TRUE)
meet_criteria(ylim, allow_class = c("numeric", "integer"), allow_NULL = TRUE)
meet_criteria(ylab, allow_class = "character", has_length = 1)
meet_criteria(xlab, allow_class = "character", has_length = 1)
meet_criteria(main, allow_class = "character", has_length = 1)
meet_criteria(axes, allow_class = "logical", has_length = 1)
data <- as.data.frame(table(x), stringsAsFactors = FALSE)
colnames(data) <- c("x", "n")
data$s <- round((data$n / sum(data$n)) * 100, 1)
if (!"S" %in% data$x) {
data <- rbind(data, data.frame(x = "S", n = 0, s = 0))
data <- rbind(data, data.frame(x = "S", n = 0, s = 0, stringsAsFactors = FALSE),
stringsAsFactors = FALSE)
}
if (!"I" %in% data$x) {
data <- rbind(data, data.frame(x = "I", n = 0, s = 0))
data <- rbind(data, data.frame(x = "I", n = 0, s = 0, stringsAsFactors = FALSE),
stringsAsFactors = FALSE)
}
if (!"R" %in% data$x) {
data <- rbind(data, data.frame(x = "R", n = 0, s = 0))
data <- rbind(data, data.frame(x = "R", n = 0, s = 0, stringsAsFactors = FALSE),
stringsAsFactors = FALSE)
}
# don't use as.rsi() here, it will confuse plot()
@@ -901,6 +1083,12 @@ barplot.rsi <- function(height,
beside = TRUE,
axes = beside,
...) {
meet_criteria(col, allow_class = "character", has_length = 3)
meet_criteria(xlab, allow_class = "character", has_length = 1)
meet_criteria(main, allow_class = "character", has_length = 1)
meet_criteria(ylab, allow_class = "character", has_length = 1)
meet_criteria(beside, allow_class = "logical", has_length = 1)
meet_criteria(axes, allow_class = "logical", has_length = 1)
if (axes == TRUE) {
par(mar = c(5, 4, 4, 2) + 0.1)
@@ -958,3 +1146,17 @@ unique.rsi <- function(x, incomparables = FALSE, ...) {
attributes(y) <- attributes(x)
y
}
check_reference_data <- function(reference_data) {
if (!identical(reference_data, AMR::rsi_translation)) {
class_rsi <- vapply(FUN.VALUE = character(1), rsi_translation, function(x) paste0("<", class(x), ">", collapse = " and "))
class_ref <- vapply(FUN.VALUE = character(1), reference_data, function(x) paste0("<", class(x), ">", collapse = " and "))
if (!all(names(class_rsi) == names(class_ref))) {
stop_("`reference_data` must have the same column names as the 'rsi_translation' data set.", call = -2)
}
if (!all(class_rsi == class_ref)) {
class_rsi[class_rsi != class_ref][1]
stop_("`reference_data` must be the same structure as the 'rsi_translation' data set. Column '", names(class_ref[class_rsi != class_ref][1]), "' is of class ", class_ref[class_rsi != class_ref][1], ", but should be of class ", class_rsi[class_rsi != class_ref][1], ".", call = -2)
}
}
}
+42 -28
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,14 +20,14 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
dots2vars <- function(...) {
# this function is to give more informative output about
# variable names in count_* and proportion_* functions
dots <- substitute(list(...))
paste(as.character(dots)[2:length(dots)], collapse = ", ")
vector_and(as.character(dots)[2:length(dots)], quotes = FALSE)
}
rsi_calc <- function(...,
@@ -36,10 +36,11 @@ rsi_calc <- function(...,
as_percent = FALSE,
only_all_tested = FALSE,
only_count = FALSE) {
stop_ifnot(is.numeric(minimum), "`minimum` must be numeric", call = -2)
stop_ifnot(is.logical(as_percent), "`as_percent` must be logical", call = -2)
stop_ifnot(is.logical(only_all_tested), "`only_all_tested` must be logical", call = -2)
meet_criteria(ab_result, allow_class = c("character", "numeric", "integer"), has_length = c(1, 2, 3), .call_depth = 1)
meet_criteria(minimum, allow_class = c("numeric", "integer"), has_length = 1, is_finite = TRUE, .call_depth = 1)
meet_criteria(as_percent, allow_class = "logical", has_length = 1, .call_depth = 1)
meet_criteria(only_all_tested, allow_class = "logical", has_length = 1, .call_depth = 1)
meet_criteria(only_count, allow_class = "logical", has_length = 1, .call_depth = 1)
data_vars <- dots2vars(...)
@@ -69,7 +70,7 @@ rsi_calc <- function(...,
}
if (length(dots) == 0 | all(dots == "df")) {
# for complete data.frames, like example_isolates %pm>% select(AMC, GEN) %pm>% proportion_S()
# and the old rsi function, which has "df" as name of the first parameter
# and the old rsi function, which has "df" as name of the first argument
x <- dots_df
} else {
# get dots that are in column names already, and the ones that will be once evaluated using dots_df or global env
@@ -77,7 +78,7 @@ rsi_calc <- function(...,
dots <- c(dots[dots %in% colnames(dots_df)],
eval(parse(text = dots[!dots %in% colnames(dots_df)]), envir = dots_df, enclos = globalenv()))
dots_not_exist <- dots[!dots %in% colnames(dots_df)]
stop_if(length(dots_not_exist) > 0, "column(s) not found: ", paste0("'", dots_not_exist, "'", collapse = ", "), call = -2)
stop_if(length(dots_not_exist) > 0, "column(s) not found: ", vector_and(dots_not_exist, quotes = TRUE), call = -2)
x <- dots_df[, dots, drop = FALSE]
}
} else if (ndots == 1) {
@@ -94,8 +95,12 @@ rsi_calc <- function(...,
}
if (is.null(x)) {
warning("argument is NULL (check if columns exist): returning NA", call. = FALSE)
return(NA)
warning_("argument is NULL (check if columns exist): returning NA", call = FALSE)
if (as_percent == TRUE) {
return(NA_character_)
} else {
return(NA_real_)
}
}
print_warning <- FALSE
@@ -117,19 +122,19 @@ rsi_calc <- function(...,
rsi_integrity_check <- as.rsi(rsi_integrity_check)
}
x_transposed <- as.list(as.data.frame(t(x)))
x_transposed <- as.list(as.data.frame(t(x), stringsAsFactors = FALSE))
if (only_all_tested == TRUE) {
# no NAs in any column
y <- apply(X = as.data.frame(lapply(x, as.integer), stringsAsFactors = FALSE),
MARGIN = 1,
FUN = min)
numerator <- sum(as.integer(y) %in% as.integer(ab_result), na.rm = TRUE)
denominator <- sum(sapply(x_transposed, function(y) !(any(is.na(y)))))
denominator <- sum(vapply(FUN.VALUE = logical(1), x_transposed, function(y) !(any(is.na(y)))))
} else {
# may contain NAs in any column
other_values <- setdiff(c(NA, levels(ab_result)), ab_result)
numerator <- sum(sapply(x_transposed, function(y) any(y %in% ab_result, na.rm = TRUE)))
denominator <- sum(sapply(x_transposed, function(y) !(all(y %in% other_values) & any(is.na(y)))))
numerator <- sum(vapply(FUN.VALUE = logical(1), x_transposed, function(y) any(y %in% ab_result, na.rm = TRUE)))
denominator <- sum(vapply(FUN.VALUE = logical(1), x_transposed, function(y) !(all(y %in% other_values) & any(is.na(y)))))
}
} else {
# x is not a data.frame
@@ -142,8 +147,13 @@ rsi_calc <- function(...,
}
if (print_warning == TRUE) {
warning("Increase speed by transforming to class <rsi> on beforehand: your_data %pm>% mutate_if(is.rsi.eligible, as.rsi)",
call. = FALSE)
if (message_not_thrown_before("rsi_calc")) {
warning_("Increase speed by transforming to class <rsi> on beforehand:\n",
" your_data %>% mutate_if(is.rsi.eligible, as.rsi)\n",
" your_data %>% mutate(across((is.rsi.eligible), as.rsi))",
call = FALSE)
remember_thrown_message("rsi_calc")
}
}
if (only_count == TRUE) {
@@ -154,7 +164,7 @@ rsi_calc <- function(...,
if (data_vars != "") {
data_vars <- paste(" for", data_vars)
}
warning("Introducing NA: only ", denominator, " results available", data_vars, " (`minimum` = ", minimum, ").", call. = FALSE)
warning_("Introducing NA: only ", denominator, " results available", data_vars, " (`minimum` = ", minimum, ").", call = FALSE)
fraction <- NA_real_
} else {
fraction <- numerator / denominator
@@ -177,17 +187,21 @@ rsi_calc_df <- function(type, # "proportion", "count" or "both"
combine_SI = TRUE,
combine_IR = FALSE,
combine_SI_missing = FALSE) {
meet_criteria(type, is_in = c("proportion", "count", "both"), has_length = 1, .call_depth = 1)
meet_criteria(data, allow_class = "data.frame", contains_column_class = "rsi", .call_depth = 1)
meet_criteria(translate_ab, allow_class = c("character", "logical"), has_length = 1, allow_NA = TRUE, .call_depth = 1)
meet_criteria(language, has_length = 1, is_in = c(LANGUAGES_SUPPORTED, ""), allow_NULL = TRUE, allow_NA = TRUE, .call_depth = 1)
meet_criteria(minimum, allow_class = c("numeric", "integer"), has_length = 1, is_finite = TRUE, .call_depth = 1)
meet_criteria(as_percent, allow_class = "logical", has_length = 1, .call_depth = 1)
meet_criteria(combine_SI, allow_class = "logical", has_length = 1, .call_depth = 1)
meet_criteria(combine_SI_missing, allow_class = "logical", has_length = 1, .call_depth = 1)
check_dataset_integrity()
stop_ifnot(is.data.frame(data), "`data` must be a data.frame", call = -2)
stop_if(any(dim(data) == 0), "`data` must contain rows and columns", call = -2)
stop_ifnot(any(sapply(data, is.rsi), na.rm = TRUE), "no columns with class <rsi> found. See ?as.rsi.", call = -2)
if (isTRUE(combine_IR) & isTRUE(combine_SI_missing)) {
combine_SI <- FALSE
}
stop_if(isTRUE(combine_SI) & isTRUE(combine_IR), "either `combine_SI` or `combine_IR` can be TRUE, not both", call = -2)
stop_ifnot(is.numeric(minimum), "`minimum` must be numeric", call = -2)
stop_ifnot(is.logical(as_percent), "`as_percent` must be logical", call = -2)
translate_ab <- get_translate_ab(translate_ab)
@@ -195,10 +209,10 @@ rsi_calc_df <- function(type, # "proportion", "count" or "both"
if (inherits(data, "grouped_df")) {
data_has_groups <- TRUE
groups <- setdiff(names(attributes(data)$groups), ".rows")
data <- data[, c(groups, colnames(data)[sapply(data, is.rsi)]), drop = FALSE]
data <- data[, c(groups, colnames(data)[vapply(FUN.VALUE = logical(1), data, is.rsi)]), drop = FALSE]
} else {
data_has_groups <- FALSE
data <- data[, colnames(data)[sapply(data, is.rsi)], drop = FALSE]
data <- data[, colnames(data)[vapply(FUN.VALUE = logical(1), data, is.rsi)], drop = FALSE]
}
data <- as.data.frame(data, stringsAsFactors = FALSE)
@@ -235,7 +249,7 @@ rsi_calc_df <- function(type, # "proportion", "count" or "both"
} else {
values <- factor(values, levels = c("S", "I", "R"), ordered = TRUE)
}
col_results <- as.data.frame(as.matrix(table(values)))
col_results <- as.data.frame(as.matrix(table(values)), stringsAsFactors = FALSE)
col_results$interpretation <- rownames(col_results)
col_results$isolates <- col_results[, 1, drop = TRUE]
if (NROW(col_results) > 0 && sum(col_results$isolates, na.rm = TRUE) > 0) {
@@ -260,7 +274,7 @@ rsi_calc_df <- function(type, # "proportion", "count" or "both"
}
out_new <- cbind(group_values, out_new)
}
out <- rbind(out, out_new)
out <- rbind(out, out_new, stringsAsFactors = FALSE)
}
}
out
+3 -4
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' @rdname proportion
@@ -32,7 +32,6 @@ rsi_df <- function(data,
as_percent = FALSE,
combine_SI = TRUE,
combine_IR = FALSE) {
rsi_calc_df(type = "both",
data = data,
translate_ab = translate_ab,
+11 -7
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,22 +20,23 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Skewness of the sample
#' Skewness of the Sample
#'
#' @description Skewness is a measure of the asymmetry of the probability distribution of a real-valued random variable about its mean.
#'
#' When negative ('left-skewed'): the left tail is longer; the mass of the distribution is concentrated on the right of a histogram. When positive ('right-skewed'): the right tail is longer; the mass of the distribution is concentrated on the left of a histogram. A normal distribution has a skewness of 0.
#' @inheritSection lifecycle Stable lifecycle
#' @inheritSection lifecycle Stable Lifecycle
#' @param x a vector of values, a [matrix] or a [data.frame]
#' @param na.rm a logical value indicating whether `NA` values should be stripped before the computation proceeds
#' @seealso [kurtosis()]
#' @rdname skewness
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @export
skewness <- function(x, na.rm = FALSE) {
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
UseMethod("skewness")
}
@@ -43,6 +44,7 @@ skewness <- function(x, na.rm = FALSE) {
#' @rdname skewness
#' @export
skewness.default <- function(x, na.rm = FALSE) {
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
x <- as.vector(x)
if (na.rm == TRUE) {
x <- x[!is.na(x)]
@@ -55,6 +57,7 @@ skewness.default <- function(x, na.rm = FALSE) {
#' @rdname skewness
#' @export
skewness.matrix <- function(x, na.rm = FALSE) {
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
apply(x, 2, skewness.default, na.rm = na.rm)
}
@@ -62,5 +65,6 @@ skewness.matrix <- function(x, na.rm = FALSE) {
#' @rdname skewness
#' @export
skewness.data.frame <- function(x, na.rm = FALSE) {
sapply(x, skewness.default, na.rm = na.rm)
meet_criteria(na.rm, allow_class = "logical", has_length = 1)
vapply(FUN.VALUE = double(1), x, skewness.default, na.rm = na.rm)
}
BIN
View File
Binary file not shown.
+32 -28
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,32 +20,32 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' Translate strings from AMR package
#' Translate Strings from AMR Package
#'
#' For language-dependent output of AMR functions, like [mo_name()], [mo_gramstain()], [mo_type()] and [ab_name()].
#' @inheritSection lifecycle Stable lifecycle
#' @details Strings will be translated to foreign languages if they are defined in a local translation file. Additions to this file can be suggested at our repository. The file can be found here: <https://github.com/msberends/AMR/blob/master/data-raw/translations.tsv>. This file will be read by all functions where a translated output can be desired, like all [mo_property()] functions ([mo_name()], [mo_gramstain()], [mo_type()], etc.) and [ab_property()] functions ([ab_name()], [ab_group()] etc.).
#' @inheritSection lifecycle Stable Lifecycle
#' @details Strings will be translated to foreign languages if they are defined in a local translation file. Additions to this file can be suggested at our repository. The file can be found here: <https://github.com/msberends/AMR/blob/master/data-raw/translations.tsv>. This file will be read by all functions where a translated output can be desired, like all [`mo_*`][mo_property()] functions (such as [mo_name()], [mo_gramstain()], [mo_type()], etc.) and [`ab_*`][ab_property()] functions (such as [ab_name()], [ab_group()], etc.).
#'
#' Currently supported languages are: `r paste(sort(gsub(";.*", "", ISOcodes::ISO_639_2[which(ISOcodes::ISO_639_2$Alpha_2 %in% LANGUAGES_SUPPORTED), "Name"])), collapse = ", ")`. Please note that currently not all these languages have translations available for all antimicrobial agents and colloquial microorganism names.
#' Currently supported languages are: `r vector_and(gsub(";.*", "", ISOcodes::ISO_639_2[which(ISOcodes::ISO_639_2$Alpha_2 %in% LANGUAGES_SUPPORTED), "Name"]), quotes = FALSE)`. Please note that currently not all these languages have translations available for all antimicrobial agents and colloquial microorganism names.
#'
#' Please suggest your own translations [by creating a new issue on our repository](https://github.com/msberends/AMR/issues/new?title=Translations).
#'
#' ## Changing the default language
#' ## Changing the Default Language
#' The system language will be used at default (as returned by `Sys.getenv("LANG")` or, if `LANG` is not set, [Sys.getlocale()]), if that language is supported. But the language to be used can be overwritten in two ways and will be checked in this order:
#'
#' 1. Setting the R option `AMR_locale`, e.g. by running `options(AMR_locale = "de")`
#' 2. Setting the system variable `LANGUAGE` or `LANG`, e.g. by adding `LANGUAGE="de_DE.utf8"` to your `.Renviron` file in your home directory
#'
#' So if the R option `AMR_locale` is set, the system variables `LANGUAGE` and `LANG` will be ignored.
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @rdname translate
#' @name translate
#' @export
#' @examples
#' # The 'language' parameter of below functions
#' # The 'language' argument of below functions
#' # will be set automatically to your system language
#' # with get_locale()
#'
@@ -73,7 +73,7 @@
#' mo_name("CoNS", language = "pt")
#' #> "Staphylococcus coagulase negativo (CoNS)"
get_locale <- function() {
# AMR versions prior to 1.3.0 used the environmental variable:
# AMR versions 1.3.0 and prior used the environmental variable:
if (!identical("", Sys.getenv("AMR_locale"))) {
options(AMR_locale = Sys.getenv("AMR_locale"))
}
@@ -83,8 +83,8 @@ get_locale <- function() {
if (lang %in% LANGUAGES_SUPPORTED) {
return(lang)
} else {
stop_("unsupported language set as option 'AMR_locale': '", lang, "' - use one of: ",
paste0("'", LANGUAGES_SUPPORTED, "'", collapse = ", "))
stop_("unsupported language set as option 'AMR_locale': \"", lang, "\" - use either ",
vector_or(LANGUAGES_SUPPORTED, quotes = TRUE))
}
} else {
# we now support the LANGUAGE system variable - return it if set
@@ -96,25 +96,25 @@ get_locale <- function() {
}
}
coerce_language_setting(Sys.getlocale())
coerce_language_setting(Sys.getlocale("LC_COLLATE"))
}
coerce_language_setting <- function(lang) {
# grepl() with ignore.case = FALSE is faster than %like%
if (grepl("^(English|en_|EN_)", lang, ignore.case = FALSE)) {
if (grepl("^(English|en_|EN_)", lang, ignore.case = FALSE, perl = TRUE)) {
# as first option to optimise speed
"en"
} else if (grepl("^(German|Deutsch|de_|DE_)", lang, ignore.case = FALSE)) {
} else if (grepl("^(German|Deutsch|de_|DE_)", lang, ignore.case = FALSE, perl = TRUE)) {
"de"
} else if (grepl("^(Dutch|Nederlands|nl_|NL_)", lang, ignore.case = FALSE)) {
} else if (grepl("^(Dutch|Nederlands|nl_|NL_)", lang, ignore.case = FALSE, perl = TRUE)) {
"nl"
} else if (grepl("^(Spanish|Espa.+ol|es_|ES_)", lang, ignore.case = FALSE)) {
} else if (grepl("^(Spanish|Espa.+ol|es_|ES_)", lang, ignore.case = FALSE, perl = TRUE)) {
"es"
} else if (grepl("^(Italian|Italiano|it_|IT_)", lang, ignore.case = FALSE)) {
} else if (grepl("^(Italian|Italiano|it_|IT_)", lang, ignore.case = FALSE, perl = TRUE)) {
"it"
} else if (grepl("^(French|Fran.+ais|fr_|FR_)", lang, ignore.case = FALSE)) {
} else if (grepl("^(French|Fran.+ais|fr_|FR_)", lang, ignore.case = FALSE, perl = TRUE)) {
"fr"
} else if (grepl("^(Portuguese|Portugu.+s|pt_|PT_)", lang, ignore.case = FALSE)) {
} else if (grepl("^(Portuguese|Portugu.+s|pt_|PT_)", lang, ignore.case = FALSE, perl = TRUE)) {
"pt"
} else {
# other language -> set to English
@@ -123,7 +123,7 @@ coerce_language_setting <- function(lang) {
}
# translate strings based on inst/translations.tsv
translate_AMR <- function(from, language = get_locale(), only_unknown = FALSE) {
translate_AMR <- function(from, language = get_locale(), only_unknown = FALSE, affect_mo_name = FALSE) {
if (is.null(language)) {
return(from)
@@ -138,24 +138,27 @@ translate_AMR <- function(from, language = get_locale(), only_unknown = FALSE) {
from_unique_translated <- from_unique
stop_ifnot(language %in% LANGUAGES_SUPPORTED,
"unsupported language: '", language, "' - use one of: ",
paste0("'", LANGUAGES_SUPPORTED, "'", collapse = ", "),
"unsupported language: \"", language, "\" - use either ",
vector_or(LANGUAGES_SUPPORTED, quotes = TRUE),
call = FALSE)
df_trans <- subset(df_trans, lang == language)
if (only_unknown == TRUE) {
df_trans <- subset(df_trans, pattern %like% "unknown")
}
if (affect_mo_name == TRUE) {
df_trans <- subset(df_trans, affect_mo_name == TRUE)
}
# default case sensitive if value if 'ignore.case' is missing:
# default: case sensitive if value if 'ignore.case' is missing:
df_trans$ignore.case[is.na(df_trans$ignore.case)] <- FALSE
# default not using regular expressions (fixed = TRUE) if 'fixed' is missing:
# default: not using regular expressions (fixed = TRUE) if 'fixed' is missing:
df_trans$fixed[is.na(df_trans$fixed)] <- TRUE
# check if text to look for is in one of the patterns
any_form_in_patterns <- tryCatch(any(from_unique %like% paste0("(", paste(df_trans$pattern, collapse = "|"), ")")),
error = function(e) {
warning("Translation not possible. Please open an issue on GitHub (https://github.com/msberends/AMR/issues).", call. = FALSE)
warning_("Translation not possible. Please open an issue on GitHub (https://github.com/msberends/AMR/issues).", call = FALSE)
return(FALSE)
})
if (NROW(df_trans) == 0 | !any_form_in_patterns) {
@@ -167,7 +170,8 @@ translate_AMR <- function(from, language = get_locale(), only_unknown = FALSE) {
replacement = df_trans$replacement[i],
x = from_unique_translated,
ignore.case = df_trans$ignore.case[i],
fixed = df_trans$fixed[i]))
fixed = df_trans$fixed[i],
perl = !df_trans$fixed[i]))
# force UTF-8 for diacritics
from_unique_translated <- enc2utf8(from_unique_translated)
+4 -4
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
#' WHOCC: WHO Collaborating Centre for Drug Statistics Methodology
@@ -35,7 +35,7 @@
#' The WHOCC is located in Oslo at the Norwegian Institute of Public Health and funded by the Norwegian government. The European Commission is the executive of the European Union and promotes its general interest.
#'
#' **NOTE: The WHOCC copyright does not allow use for commercial purposes, unlike any other info from this package.** See <https://www.whocc.no/copyright_disclaimer/.>
#' @inheritSection AMR Read more on our website!
#' @inheritSection AMR Read more on Our Website!
#' @name WHOCC
#' @rdname WHOCC
#' @examples
+21 -107
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,34 +20,14 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
.onLoad <- function(libname, pkgname) {
assign(x = "AB_lookup",
value = create_AB_lookup(),
envir = asNamespace("AMR"))
assign(x = "MO_lookup",
value = create_MO_lookup(),
envir = asNamespace("AMR"))
assign(x = "MO.old_lookup",
value = create_MO.old_lookup(),
envir = asNamespace("AMR"))
assign(x = "LANGUAGES_SUPPORTED",
value = sort(c("en", unique(translations_file$lang))),
envir = asNamespace("AMR"))
assign(x = "MO_CONS",
value = create_species_cons_cops("CoNS"),
envir = asNamespace("AMR"))
assign(x = "MO_COPS",
value = create_species_cons_cops("CoPS"),
envir = asNamespace("AMR"))
# set up package environment, used by numerous AMR functions
pkg_env <- new.env(hash = FALSE)
pkg_env$mo_failed <- character(0)
.onLoad <- function(libname, pkgname) {
# Support for tibble headers (type_sum) and tibble columns content (pillar_shaft)
# without the need to depend on other packages. This was suggested by the
# developers of the vctrs package:
@@ -70,6 +50,13 @@
s3_register("skimr::get_skimmers", "rsi")
s3_register("skimr::get_skimmers", "mic")
s3_register("skimr::get_skimmers", "disk")
# if mo source exists, fire it up (see mo_source())
try({
if (file.exists(getOption("AMR_mo_source", "~/mo_source.rds"))) {
invisible(get_mo_source())
}
}, silent = TRUE)
}
.onAttach <- function(...) {
@@ -77,87 +64,14 @@
if (!interactive() || stats::runif(1) > 0.1 || isTRUE(as.logical(getOption("AMR_silentstart", FALSE)))) {
return()
}
packageStartupMessage("Thank you for using the AMR package! ",
"If you have a minute, please anonymously fill in this short questionnaire to improve the package and its functionalities:",
"\nhttps://msberends.github.io/AMR/survey.html",
"\n[ prevent his notice with suppressPackageStartupMessages(library(AMR)) or use options(AMR_silentstart = TRUE) ]")
packageStartupMessage(word_wrap("Thank you for using the AMR package! ",
"If you have a minute, please anonymously fill in this short questionnaire to improve the package and its functionalities: ",
font_blue("https://msberends.github.io/AMR/survey.html\n"),
"[prevent his notice with ",
font_bold("suppressPackageStartupMessages(library(AMR))"),
" or use ",
font_bold("options(AMR_silentstart = TRUE)"), "]"))
}
create_species_cons_cops <- function(type = c("CoNS", "CoPS")) {
# Determination of which staphylococcal species are CoNS/CoPS according to Becker et al.:
# https://cmr.asm.org/content/cmr/27/4/870/F6.large.jpg
# this function returns class <mo>
MO_staph <- AMR::microorganisms
MO_staph <- MO_staph[which(MO_staph$genus == "Staphylococcus"), , drop = FALSE]
if (type == "CoNS") {
MO_staph[which(MO_staph$species %in% c("coagulase-negative",
"arlettae", "auricularis", "capitis",
"caprae", "carnosus", "chromogenes", "cohnii", "condimenti",
"devriesei", "epidermidis", "equorum", "felis",
"fleurettii", "gallinarum", "haemolyticus",
"hominis", "jettensis", "kloosii", "lentus",
"lugdunensis", "massiliensis", "microti",
"muscae", "nepalensis", "pasteuri", "petrasii",
"pettenkoferi", "piscifermentans", "rostri",
"saccharolyticus", "saprophyticus", "sciuri",
"stepanovicii", "simulans", "succinus",
"vitulinus", "warneri", "xylosus")
| (MO_staph$species == "schleiferi" & MO_staph$subspecies %in% c("schleiferi", ""))),
"mo", drop = TRUE]
} else if (type == "CoPS") {
MO_staph[which(MO_staph$species %in% c("coagulase-positive",
"simiae", "agnetis",
"delphini", "lutrae",
"hyicus", "intermedius",
"pseudintermedius", "pseudointermedius",
"schweitzeri", "argenteus")
| (MO_staph$species == "schleiferi" & MO_staph$subspecies == "coagulans")),
"mo", drop = TRUE]
}
}
create_AB_lookup <- function() {
AB_lookup <- AMR::antibiotics
AB_lookup$generalised_name <- generalise_antibiotic_name(AB_lookup$name)
AB_lookup$generalised_synonyms <- lapply(AB_lookup$synonyms, generalise_antibiotic_name)
AB_lookup$generalised_abbreviations <- lapply(AB_lookup$abbreviations, generalise_antibiotic_name)
AB_lookup$generalised_loinc <- lapply(AB_lookup$loinc, generalise_antibiotic_name)
AB_lookup
}
create_MO_lookup <- function() {
MO_lookup <- AMR::microorganisms
MO_lookup$kingdom_index <- NA_real_
MO_lookup[which(MO_lookup$kingdom == "Bacteria" | MO_lookup$mo == "UNKNOWN"), "kingdom_index"] <- 1
MO_lookup[which(MO_lookup$kingdom == "Fungi"), "kingdom_index"] <- 2
MO_lookup[which(MO_lookup$kingdom == "Protozoa"), "kingdom_index"] <- 3
MO_lookup[which(MO_lookup$kingdom == "Archaea"), "kingdom_index"] <- 4
# all the rest
MO_lookup[which(is.na(MO_lookup$kingdom_index)), "kingdom_index"] <- 5
# use this paste instead of `fullname` to work with Viridans Group Streptococci, etc.
MO_lookup$fullname_lower <- tolower(trimws(paste(MO_lookup$genus,
MO_lookup$species,
MO_lookup$subspecies)))
ind <- MO_lookup$genus == "" | grepl("^[(]unknown ", MO_lookup$fullname)
MO_lookup[ind, "fullname_lower"] <- tolower(MO_lookup[ind, "fullname"])
MO_lookup$fullname_lower <- trimws(gsub("[^.a-z0-9/ \\-]+", "", MO_lookup$fullname_lower, perl = TRUE))
# add a column with only "e coli" like combinations
MO_lookup$g_species <- gsub("^([a-z])[a-z]+ ([a-z]+) ?.*", "\\1 \\2", MO_lookup$fullname_lower, perl = TRUE)
# so arrange data on prevalence first, then kingdom, then full name
MO_lookup[order(MO_lookup$prevalence, MO_lookup$kingdom_index, MO_lookup$fullname_lower), ]
}
create_MO.old_lookup <- function() {
MO.old_lookup <- AMR::microorganisms.old
MO.old_lookup$fullname_lower <- trimws(gsub("[^.a-z0-9/ \\-]+", "", tolower(trimws(MO.old_lookup$fullname))))
# add a column with only "e coli"-like combinations
MO.old_lookup$g_species <- trimws(gsub("^([a-z])[a-z]+ ([a-z]+) ?.*", "\\1 \\2", MO.old_lookup$fullname_lower))
# so arrange data on prevalence first, then full name
MO.old_lookup[order(MO.old_lookup$prevalence, MO.old_lookup$fullname_lower), ]
}
+10 -3
View File
@@ -2,11 +2,16 @@
# `AMR` (for R)
<img src="https://www.r-pkg.org/badges/version-ago/AMR" />
<img src="https://cranlogs.r-pkg.org/badges/grand-total/AMR" />
[![CRAN](https://www.r-pkg.org/badges/version-ago/AMR)](https://cran.r-project.org/package=AMR)
[![CRANlogs](https://cranlogs.r-pkg.org/badges/grand-total/AMR)](https://cran.r-project.org/package=AMR)
![R-code-check](https://github.com/msberends/AMR/workflows/R-code-check/badge.svg?branch=master)
[![CodeFactor](https://www.codefactor.io/repository/github/msberends/amr/badge)](https://www.codefactor.io/repository/github/msberends/amr)
[![Codecov](https://codecov.io/gh/msberends/AMR/branch/master/graph/badge.svg)](https://codecov.io/gh/msberends/AMR?branch=master)
<img src="https://msberends.github.io/AMR/works_great_on.png" align="center" height="150px" />
The latest built **source package** (`AMR_latest.tar.gz`) can be found in folder [/data-raw/](data-raw).
`AMR` is a free, open-source and independent R package to simplify the analysis and prediction of Antimicrobial Resistance (AMR) and to work with microbial and antimicrobial data and properties, by using evidence-based methods. Our aim is to provide a standard for clean and reproducible antimicrobial resistance data analysis, that can therefore empower epidemiological analyses to continuously enable surveillance and treatment evaluation in any setting.
After installing this package, R knows ~70,000 distinct microbial species and all ~550 antibiotic, antimycotic and antiviral drugs by name and code (including ATC, EARS-NET, LOINC and SNOMED CT), and knows all about valid R/SI and MIC values. It supports any data format, including WHONET/EARS-Net data.
@@ -15,11 +20,13 @@ This package is fully independent of any other R package and works on Windows, m
This is the development source of the `AMR` package for R. Not a developer? Then please visit our website [https://msberends.github.io/AMR/](https://msberends.github.io/AMR/) to read more about this package.
*NOTE: this source code is on GitHub (https://github.com/msberends/AMR), but also automatically mirrored to GitLab (https://gitlab.com/msberends/AMR).*
*NOTE: this source code is on GitHub (https://github.com/msberends/AMR), but also automatically mirrored to our university's Gitea server (https://git.web.rug.nl/P281424/AMR) and to GitLab (https://gitlab.com/msberends/AMR).*
### How to get this package
Please see [our website](https://msberends.github.io/AMR/#get-this-package).
Bottom line: `install.packages("AMR")`
### Copyright
This R package is licensed under the [GNU General Public License (GPL) v2.0](https://github.com/msberends/AMR/blob/master/LICENSE). In a nutshell, this means that this package:
+24 -19
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
title: "AMR (for R)"
@@ -99,18 +99,19 @@ reference:
for more information about how to work with functions in this package.
contents:
- "`AMR`"
- "`example_isolates`"
- "`microorganisms`"
- "`microorganisms.codes`"
- "`microorganisms.old`"
- "`antibiotics`"
- "`intrinsic_resistant`"
- "`dosage`"
- "`catalogue_of_life`"
- "`catalogue_of_life_version`"
- "`WHOCC`"
- "`lifecycle`"
- "`microorganisms`"
- "`antibiotics`"
- "`intrinsic_resistant`"
- "`example_isolates`"
- "`example_isolates_unclean`"
- "`rsi_translation`"
- "`microorganisms.codes`"
- "`microorganisms.old`"
- "`WHONET`"
- title: "Preparing data: microorganisms"
@@ -143,15 +144,17 @@ reference:
- "`as.disk`"
- "`eucast_rules`"
- "`plot`"
- "`isolate_identifier`"
- title: "Analysing data: antimicrobial resistance"
desc: >
Use these function for the analysis part. You can use `susceptibility()` or `resistance()` on any antibiotic column.
Be sure to first select the isolates that are appropiate for analysis, by using `first_isolate()`.
Be sure to first select the isolates that are appropiate for analysis, by using `first_isolate()` or `is_new_episode()`.
You can also filter your data on certain resistance in certain antibiotic classes (`filter_ab_class()`), or determine multi-drug resistant microorganisms (MDRO, `mdro()`).
contents:
- "`proportion`"
- "`count`"
- "`is_new_episode`"
- "`first_isolate`"
- "`key_antibiotics`"
- "`mdro`"
@@ -178,23 +181,23 @@ reference:
- "`like`"
- "`mo_matching_score`"
- "`pca`"
- "`random`"
- title: "Other: statistical tests"
desc: >
Some statistical tests or methods are not part of base R and are added to this package for convenience.
Some statistical tests or methods are not part of base R and were added to this package for convenience.
contents:
- "`g.test`"
- "`kurtosis`"
- "`skewness`"
- "`p_symbol`"
# - title: "Other: deprecated functions"
# desc: >
# These functions are deprecated, meaning that they will still
# work but show a warning with every use and will be removed
# in a future version.
# contents:
# - "`AMR-deprecated`"
- title: "Other: deprecated functions"
desc: >
These functions are deprecated, meaning that they will still
work but show a warning with every use and will be removed
in a future version.
contents:
- "`AMR-deprecated`"
authors:
Matthijs S. Berends:
@@ -211,6 +214,8 @@ authors:
href: https://www.rug.nl/staff/c.glasner/
template:
# this requires the 'preferably' package, https://github.com/amirmasoudabdol/preferably/
# package: preferably
assets: "pkgdown/logos" # use logos in this folder
params:
noindex: false
+3 -3
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
codecov:
+1 -3
View File
@@ -1,3 +1 @@
* Edited the unit tests, so they will run under 10 minutes on CRAN (using testthat::skip_on_cran() on some tests).
* Since version 0.3.0 (2018-08-14), CHECK returns a NOTE for having a data directory over 3 MB. This is needed to offer users reference data for the complete taxonomy of microorganisms - one of the most important features of this package.
* Ever since one of the first CRAN releases, CHECK returns a NOTE for having a data and R directory over 3 MB. This is needed to offer users reference data for the complete taxonomy of microorganisms - one of the most important features of this package.
Binary file not shown.
Binary file not shown.
+156 -19
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,15 +20,121 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
# Run this file to update the package using: -------------------------------
# source("data-raw/internals.R")
# --------------------------------------------------------------------------
# Run this file to update the package using:
# source("data-raw/_internals.R")
library(dplyr, warn.conflicts = FALSE)
devtools::load_all(quiet = TRUE)
old_globalenv <- ls(envir = globalenv())
# Helper functions --------------------------------------------------------
create_species_cons_cops <- function(type = c("CoNS", "CoPS")) {
# Determination of which staphylococcal species are CoNS/CoPS according to:
# - Becker et al. 2014, PMID 25278577
# - Becker et al. 2019, PMID 30872103
# - Becker et al. 2020, PMID 32056452
# this function returns class <mo>
MO_staph <- AMR::microorganisms
MO_staph <- MO_staph[which(MO_staph$genus == "Staphylococcus"), , drop = FALSE]
if (type == "CoNS") {
MO_staph[which(MO_staph$species %in% c("coagulase-negative", "argensis", "arlettae",
"auricularis", "caeli", "capitis", "caprae",
"carnosus", "chromogenes", "cohnii", "condimenti",
"debuckii", "devriesei", "edaphicus", "epidermidis",
"equorum", "felis", "fleurettii", "gallinarum",
"haemolyticus", "hominis", "jettensis", "kloosii",
"lentus", "lugdunensis", "massiliensis", "microti",
"muscae", "nepalensis", "pasteuri", "petrasii",
"pettenkoferi", "piscifermentans", "pseudoxylosus",
"pulvereri", "rostri", "saccharolyticus", "saprophyticus",
"sciuri", "simulans", "stepanovicii", "succinus",
"vitulinus", "vitulus", "warneri", "xylosus")
| (MO_staph$species == "schleiferi" & MO_staph$subspecies %in% c("schleiferi", ""))),
"mo", drop = TRUE]
} else if (type == "CoPS") {
MO_staph[which(MO_staph$species %in% c("coagulase-positive",
"agnetis", "argenteus",
"cornubiensis",
"delphini", "lutrae",
"hyicus", "intermedius",
"pseudintermedius", "pseudointermedius",
"schweitzeri", "simiae")
| (MO_staph$species == "schleiferi" & MO_staph$subspecies == "coagulans")),
"mo", drop = TRUE]
}
}
create_AB_lookup <- function() {
AB_lookup <- AMR::antibiotics
AB_lookup$generalised_name <- generalise_antibiotic_name(AB_lookup$name)
AB_lookup$generalised_synonyms <- lapply(AB_lookup$synonyms, generalise_antibiotic_name)
AB_lookup$generalised_abbreviations <- lapply(AB_lookup$abbreviations, generalise_antibiotic_name)
AB_lookup$generalised_loinc <- lapply(AB_lookup$loinc, generalise_antibiotic_name)
AB_lookup$generalised_all <- unname(lapply(as.list(as.data.frame(t(AB_lookup[,
c("ab", "atc", "cid", "name",
colnames(AB_lookup)[colnames(AB_lookup) %like% "generalised"]),
drop = FALSE]),
stringsAsFactors = FALSE)),
function(x) {
x <- generalise_antibiotic_name(unname(unlist(x)))
x[x != ""]
}))
AB_lookup
}
create_MO_lookup <- function() {
MO_lookup <- AMR::microorganisms
MO_lookup$kingdom_index <- NA_real_
MO_lookup[which(MO_lookup$kingdom == "Bacteria" | MO_lookup$mo == "UNKNOWN"), "kingdom_index"] <- 1
MO_lookup[which(MO_lookup$kingdom == "Fungi"), "kingdom_index"] <- 2
MO_lookup[which(MO_lookup$kingdom == "Protozoa"), "kingdom_index"] <- 3
MO_lookup[which(MO_lookup$kingdom == "Archaea"), "kingdom_index"] <- 4
# all the rest
MO_lookup[which(is.na(MO_lookup$kingdom_index)), "kingdom_index"] <- 5
# use this paste instead of `fullname` to work with Viridans Group Streptococci, etc.
MO_lookup$fullname_lower <- tolower(trimws(paste(MO_lookup$genus,
MO_lookup$species,
MO_lookup$subspecies)))
ind <- MO_lookup$genus == "" | grepl("^[(]unknown ", MO_lookup$fullname)
MO_lookup[ind, "fullname_lower"] <- tolower(MO_lookup[ind, "fullname"])
MO_lookup$fullname_lower <- trimws(gsub("[^.a-z0-9/ \\-]+", "", MO_lookup$fullname_lower, perl = TRUE))
# add a column with only "e coli" like combinations
MO_lookup$g_species <- gsub("^([a-z])[a-z]+ ([a-z]+) ?.*", "\\1 \\2", MO_lookup$fullname_lower, perl = TRUE)
# so arrange data on prevalence first, then kingdom, then full name
MO_lookup[order(MO_lookup$prevalence, MO_lookup$kingdom_index, MO_lookup$fullname_lower), ]
}
create_MO.old_lookup <- function() {
MO.old_lookup <- AMR::microorganisms.old
MO.old_lookup$fullname_lower <- trimws(gsub("[^.a-z0-9/ \\-]+", "", tolower(trimws(MO.old_lookup$fullname))))
# add a column with only "e coli"-like combinations
MO.old_lookup$g_species <- trimws(gsub("^([a-z])[a-z]+ ([a-z]+) ?.*", "\\1 \\2", MO.old_lookup$fullname_lower))
# so arrange data on prevalence first, then full name
MO.old_lookup[order(MO.old_lookup$prevalence, MO.old_lookup$fullname_lower), ]
}
create_intr_resistance <- function() {
# for mo_is_intrinsic_resistant() - saves a lot of time when executed on this vector
paste(AMR::microorganisms[match(AMR::intrinsic_resistant$microorganism, AMR::microorganisms$fullname), "mo", drop = TRUE],
AMR::antibiotics[match(AMR::intrinsic_resistant$antibiotic, AMR::antibiotics$name), "ab", drop = TRUE])
}
# Save internal data sets to R/sysdata.rda --------------------------------
# See 'data-raw/eucast_rules.tsv' for the EUCAST reference file
library(dplyr, warn.conflicts = FALSE)
eucast_rules_file <- utils::read.delim(file = "data-raw/eucast_rules.tsv",
skip = 10,
sep = "\t",
@@ -48,7 +154,7 @@ eucast_rules_file <- utils::read.delim(file = "data-raw/eucast_rules.tsv",
mutate(reference.rule_group = as.character(reference.rule_group)) %>%
select(-sorting_rule)
# Translations ----
# Translations
translations_file <- utils::read.delim(file = "data-raw/translations.tsv",
sep = "\t",
stringsAsFactors = FALSE,
@@ -62,23 +168,42 @@ translations_file <- utils::read.delim(file = "data-raw/translations.tsv",
allowEscapes = TRUE, # else "\\1" will be imported as "\\\\1"
quote = "")
# Old microorganism codes -------------------------------------------------
# Old microorganism codes
microorganisms.translation <- readRDS("data-raw/microorganisms.translation.rds")
# for mo_is_intrinsic_resistant() - saves a lot of time when executed on this vector
INTRINSIC_R <- create_intr_resistance()
# for checking input in `language` argument in e.g. mo_*() and ab_*() functions
LANGUAGES_SUPPORTED <- sort(c("en", unique(translations_file$lang)))
# vectors of CoNS and CoPS, improves speed in as.mo()
MO_CONS <- create_species_cons_cops("CoNS")
MO_COPS <- create_species_cons_cops("CoPS")
# reference data - they have additional columns compared to `antibiotics` and `microorganisms` to improve speed
AB_lookup <- create_AB_lookup()
MO_lookup <- create_MO_lookup()
MO.old_lookup <- create_MO.old_lookup()
# Export to package as internal data ----
usethis::use_data(eucast_rules_file, translations_file, microorganisms.translation,
usethis::use_data(eucast_rules_file,
translations_file,
microorganisms.translation,
INTRINSIC_R,
LANGUAGES_SUPPORTED,
MO_CONS,
MO_COPS,
AB_lookup,
MO_lookup,
MO.old_lookup,
internal = TRUE,
overwrite = TRUE,
version = 2,
compress = "xz")
# Remove from global environment ----
rm(eucast_rules_file)
rm(translations_file)
rm(microorganisms.translation)
# Export data sets to the repository in different formats -----------------
# Save to raw data to repository ----
write_md5 <- function(object) {
conn <- file(paste0("data-raw/", deparse(substitute(object)), ".md5"))
writeLines(digest::digest(object, "md5"), conn)
@@ -93,7 +218,7 @@ changed_md5 <- function(object) {
}, error = function(e) TRUE)
}
usethis::ui_done(paste0("Saving raw data to {usethis::ui_value('/data-raw/')}"))
devtools::load_all(quiet = TRUE)
# give official names to ABs and MOs
rsi <- dplyr::mutate(rsi_translation, ab = ab_name(ab), mo = mo_name(mo))
if (changed_md5(rsi)) {
@@ -159,5 +284,17 @@ if (changed_md5(intrinsic_resistant)) {
try(openxlsx::write.xlsx(intrinsic_resistant, "data-raw/intrinsic_resistant.xlsx"), silent = TRUE)
}
rm(write_md5)
rm(changed_md5)
if (changed_md5(dosage)) {
write_md5(dosage)
try(saveRDS(dosage, "data-raw/dosage.rds", version = 2, compress = "xz"), silent = TRUE)
try(write.table(dosage, "data-raw/dosage.txt", sep = "\t", na = "", row.names = FALSE), silent = TRUE)
try(haven::write_sas(dosage, "data-raw/dosage.sas"), silent = TRUE)
try(haven::write_sav(dosage, "data-raw/dosage.sav"), silent = TRUE)
try(haven::write_dta(dosage, "data-raw/dosage.dta"), silent = TRUE)
try(openxlsx::write.xlsx(dosage, "data-raw/dosage.xlsx"), silent = TRUE)
}
# remove leftovers from global env
current_globalenv <- ls(envir = globalenv())
rm(list = current_globalenv[!current_globalenv %in% old_globalenv])
rm(current_globalenv)
+1 -1
View File
@@ -1 +1 @@
a30faa0e4475d440d1bb8e44e6857062
fa68ab044001078f290218a7de6cc5c4
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+3 -2
View File
@@ -37,6 +37,8 @@
"BEK" 439318 "Bekanamycin" "Aminoglycosides" "" "c(\"aminodeoxykanamycin\", \"becanamicina\", \"bekanamycin\", \"bekanamycine\", \"bekanamycinum\", \"nebramycin v\")" "character(0)"
"BNB" "J01CE08" "Benzathine benzylpenicillin" "Beta-lactams/penicillins" "Beta-lactam antibacterials, penicillins" "Beta-lactamase sensitive penicillins" "" "" 3.6 "g" ""
"BNP" "J01CE10" 64725 "Benzathine phenoxymethylpenicillin" "Beta-lactams/penicillins" "Beta-lactam antibacterials, penicillins" "Beta-lactamase sensitive penicillins" "" "c(\"bicillin v\", \"biphecillin\")" 2 "g" "character(0)"
"PEN" "J01CE01" 5904 "Benzylpenicillin" "Beta-lactams/penicillins" "Combinations of antibacterials" "Combinations of antibacterials" "c(\"bepe\", \"pen\", \"peni\", \"peni g\", \"penicillin\", \"penicillin g\", \"pg\")" "c(\"abbocillin\", \"ayercillin\", \"bencilpenicilina\", \"benzopenicillin\", \"benzyl penicillin\", \"benzylpenicillin\", \"benzylpenicillin g\", \"benzylpenicilline\", \"benzylpenicillinum\", \"bicillin\", \"cillora\", \"cilloral\", \"cilopen\", \"compocillin g\", \"cosmopen\", \"dropcillin\", \"free penicillin g\", \"free penicillin ii\", \"galofak\", \"gelacillin\", \"liquacillin\", \"megacillin\", \"pencillin g\", \"penicillin\", \"penicilling\", \"pentids\", \"permapen\", \"pfizerpen\", \"pfizerpen g\", \"pharmacillin\", \"pradupen\", \"specilline g\", \"ursopen\"
)" 3.6 "g" "3913-1"
"BES" 10178705 "Besifloxacin" "Quinolones" "" "besifloxacin" "character(0)"
"BIA" 71339 "Biapenem" "Carbapenems" "" "c(\"biapenem\", \"biapenern\", \"bipenem\", \"omegacin\")" "character(0)"
"BCZ" 65807 "Bicyclomycin (Bicozamycin)" "Other antibacterials" "" "c(\"aizumycin\", \"bacfeed\", \"bacteron\", \"bicozamicina\", \"bicozamycin\", \"bicozamycine\", \"bicozamycinum\")" "character(0)"
@@ -328,8 +330,6 @@
"PAZ" "J01MA18" 65957 "Pazufloxacin" "Quinolones" "Quinolone antibacterials" "Fluoroquinolones" "" "c(\"pazufloxacin\", \"pazufloxacine\", \"pazufloxacino\", \"pazufloxacinum\")" 1 "g" "character(0)"
"PEF" "J01MA03" 51081 "Pefloxacin" "Quinolones" "Quinolone antibacterials" "Fluoroquinolones" "c(\"\", \"pefl\")" "c(\"abactal\", \"labocton\", \"pefloxacin\", \"pefloxacine\", \"pefloxacino\", \"pefloxacinum\", \"perfloxacin\", \"silver pefloxacin\")" 0.8 "g" 0.8 "g" "3906-5"
"PNM" "J01CE06" 10250769 "Penamecillin" "Beta-lactams/penicillins" "Beta-lactam antibacterials, penicillins" "Beta-lactamase sensitive penicillins" "" "c(\"hydroxymethyl\", \"penamecilina\", \"penamecillin\", \"penamecillina\", \"penamecilline\", \"penamecillinum\")" 1.05 "g" "character(0)"
"PEN" "J01CE01" 5904 "Benzylpenicillin" "Beta-lactams/penicillins" "Combinations of antibacterials" "Combinations of antibacterials" "c(\"bepe\", \"pen\", \"peni\", \"peni g\", \"penicillin\", \"penicillin g\", \"pg\")" "c(\"abbocillin\", \"ayercillin\", \"bencilpenicilina\", \"benzopenicillin\", \"benzyl penicillin\", \"benzylpenicillin\", \"benzylpenicillin g\", \"benzylpenicilline\", \"benzylpenicillinum\", \"bicillin\", \"cillora\", \"cilloral\", \"cilopen\", \"compocillin g\", \"cosmopen\", \"dropcillin\", \"free penicillin g\", \"free penicillin ii\", \"galofak\", \"gelacillin\", \"liquacillin\", \"megacillin\", \"pencillin g\", \"penicillin\", \"penicilling\", \"pentids\", \"permapen\", \"pfizerpen\", \"pfizerpen g\", \"pharmacillin\", \"pradupen\", \"specilline g\", \"ursopen\"
)" 3.6 "g" "3913-1"
"PNO" "Penicillin/novobiocin" "Beta-lactams/penicillins" "" "" ""
"PSU" "Penicillin/sulbactam" "Beta-lactams/penicillins" "" "" ""
"PNM1" "J01AA10" 54686187 "Penimepicycline" "Tetracyclines" "Tetracyclines" "Tetracyclines" "" "c(\"duamine\", \"hydrocycline\", \"penetracyne\", \"penimepiciclina\", \"penimepicycline\", \"penimepicyclinum\")" "character(0)"
@@ -354,6 +354,7 @@
"POS" "J02AC04" 468595 "Posaconazole" "Antifungals/antimycotics" "Antimycotics for systemic use" "Triazole derivatives" "posa" "c(\"noxafil\", \"posaconazole\", \"posaconazole sp\", \"posconazole\")" 0.3 "g" 0.3 "g" "c(\"53731-6\", \"80545-7\")"
"PRA" 9802884 "Pradofloxacin" "Quinolones" "" "pradofloxacin" "character(0)"
"PRX" 71455 "Premafloxacin" "Quinolones" "" "premafloxacin" "character(0)"
"PMD" "J04AK08" 456199 "Pretomanid" "Antimycobacterials" "Drugs for treatment of tuberculosis" "Other drugs for treatment of tuberculosis" "" "" ""
"PRM" 6446787 "Primycin" "Macrolides/lincosamides" "" "" ""
"PRI" "J01FG01" 11979535 "Pristinamycin" "Macrolides/lincosamides" "Macrolides, lincosamides and streptogramins" "Streptogramins" "c(\"\", \"pris\")" "c(\"eskalin v\", \"mikamycin\", \"mikamycine\", \"mikamycinum\", \"ostreogrycinum\", \"pristinamycine\", \"pristinamycinum\", \"stafac\", \"stafytracine\", \"staphylomycin\", \"starfac\", \"streptogramin\", \"vernamycin\", \"virgimycin\", \"virgimycine\", \"virginiamycina\", \"virginiamycine\", \"virginiamycinum\")" 2 "g" "character(0)"
"PRB" "J01CE09" 5903 "Procaine benzylpenicillin" "Beta-lactams/penicillins" "Beta-lactam antibacterials, penicillins" "Beta-lactamase sensitive penicillins" "" "c(\"depocillin\", \"duphapen\", \"hostacillin\", \"hydracillin\", \"jenacillin o\", \"nopcaine\", \"penicillin procaine\", \"retardillin\", \"vetspen\", \"vitablend\")" 0.6 "g" "character(0)"
Binary file not shown.
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
58d6a0589aea598420e37045fb04a5ae
Binary file not shown.
Binary file not shown.
Binary file not shown.
+170
View File
@@ -0,0 +1,170 @@
"ab" "name" "type" "dose" "dose_times" "administration" "notes" "original_txt" "eucast_version"
"AMK" "Amikacin" "standard_dosage" "25-30 mg/kg" 1 "iv" "" "25-30 mg/kg x 1 iv" 11
"AMX" "Amoxicillin" "high_dosage" "2 g" 6 "iv" "" "2 g x 6 iv" 11
"AMX" "Amoxicillin" "standard_dosage" "1 g" 3 "iv" "" "1 g x 3-4 iv" 11
"AMX" "Amoxicillin" "high_dosage" "0.75-1 g" 3 "oral" "" "0.75-1 g x 3 oral" 11
"AMX" "Amoxicillin" "standard_dosage" "0.5 g" 3 "oral" "" "0.5 g x 3 oral" 11
"AMX" "Amoxicillin" "uncomplicated_uti" "0.5 g" 3 "oral" "" "0.5 g x 3 oral" 11
"AMC" "Amoxicillin/clavulanic acid" "high_dosage" "2 g + 0.2 g" 3 "iv" "" "(2 g amoxicillin + 0.2 g clavulanic acid) x 3 iv" 11
"AMC" "Amoxicillin/clavulanic acid" "standard_dosage" "1 g + 0.2 g" 3 "iv" "" "(1 g amoxicillin + 0.2 g clavulanic acid) x 3-4 iv" 11
"AMC" "Amoxicillin/clavulanic acid" "high_dosage" "0.875 g + 0.125 g" 3 "oral" "" "(0.875 g amoxicillin + 0.125 g clavulanic acid) x 3 oral" 11
"AMC" "Amoxicillin/clavulanic acid" "standard_dosage" "0.5 g + 0.125 g" 3 "oral" "" "(0.5 g amoxicillin + 0.125 g clavulanic acid) x 3 oral" 11
"AMC" "Amoxicillin/clavulanic acid" "uncomplicated_uti" "0.5 g + 0.125 g" 3 "oral" "" "(0.5 g amoxicillin + 0.125 g clavulanic acid) x 3 oral" 11
"AMP" "Ampicillin" "high_dosage" "2 g" 4 "iv" "" "2 g x 4 iv" 11
"AMP" "Ampicillin" "standard_dosage" "2 g" 3 "iv" "" "2 g x 3 iv" 11
"SAM" "Ampicillin/sulbactam" "high_dosage" "2 g + 1 g" 4 "iv" "" "(2 g ampicillin + 1 g sulbactam) x 4 iv" 11
"SAM" "Ampicillin/sulbactam" "standard_dosage" "2 g + 1 g" 3 "iv" "" "(2 g ampicillin + 1 g sulbactam) x 3 iv" 11
"AZM" "Azithromycin" "standard_dosage" "0.5 g" 1 "iv" "" "0.5 g x 1 iv" 11
"AZM" "Azithromycin" "standard_dosage" "0.5 g" 1 "oral" "" "0.5 g x 1 oral" 11
"ATM" "Aztreonam" "high_dosage" "2 g" 4 "iv" "" "2 g x 4 iv" 11
"ATM" "Aztreonam" "standard_dosage" "1 g" 3 "iv" "" "1 g x 3 iv" 11
"PEN" "Benzylpenicillin" "high_dosage" "1.2 g" 4 "iv" "" "1.2 g (2 MU) x 4-6 iv" 11
"PEN" "Benzylpenicillin" "standard_dosage" "0.6 g" 4 "iv" "" "0.6 g (1 MU) x 4 iv" 11
"CEC" "Cefaclor" "high_dosage" "1 g" 3 "oral" "" "1 g x 3 oral" 11
"CEC" "Cefaclor" "standard_dosage" "0.25-0.5 g" 3 "oral" "" "0.25-0.5 g x 3 oral" 11
"CFR" "Cefadroxil" "standard_dosage" "0.5-1 g" 2 "oral" "" "0.5-1 g x 2 oral" 11
"CFR" "Cefadroxil" "uncomplicated_uti" "0.5-1 g" 2 "oral" "" "0.5-1 g x 2 oral" 11
"CZO" "Cefazolin" "high_dosage" "2 g" 3 "iv" "" "2 g x 3 iv" 11
"CZO" "Cefazolin" "standard_dosage" "1 g" 3 "iv" "" "1 g x 3 iv" 11
"FEP" "Cefepime" "high_dosage" "2 g" 3 "iv" "" "2 g x 3 iv" 11
"FEP" "Cefepime" "standard_dosage" "2 g" 2 "iv" "" "2 g x 2 iv" 11
"FDC" "Cefiderocol" "standard_dosage" "2 g" 3 "iv" "over 3 hours" "2 g x 3 iv over 3 hours" 11
"CFM" "Cefixime" "standard_dosage" "0.2-0.4 g" 2 "oral" "" "0.2-0.4 g x 2 oral" 11
"CFM" "Cefixime" "uncomplicated_uti" "0.2-0.4 g" 2 "oral" "" "0.2-0.4 g x 2 oral" 11
"CTX" "Cefotaxime" "high_dosage" "2 g" 3 "iv" "" "2 g x 3 iv" 11
"CTX" "Cefotaxime" "standard_dosage" "1 g" 3 "iv" "" "1 g x 3 iv" 11
"CPD" "Cefpodoxime" "standard_dosage" "0.1-0.2 g" 2 "oral" "" "0.1-0.2 g x 2 oral" 11
"CPD" "Cefpodoxime" "uncomplicated_uti" "0.1-0.2 g" 2 "oral" "" "0.1-0.2 g x 2 oral" 11
"CPT" "Ceftaroline" "high_dosage" "0.6 g" 3 "iv" "over 2 hours" "0.6 g x 3 iv over 2 hours" 11
"CPT" "Ceftaroline" "standard_dosage" "0.6 g" 2 "iv" "over 1 hour" "0.6 g x 2 iv over 1 hour" 11
"CAZ" "Ceftazidime" "high_dosage" "1 g" 6 "iv" "" "1 g x 6 iv" 11
"CAZ" "Ceftazidime" "standard_dosage" "1 g" 3 "iv" "" "1 g x 3 iv" 11
"CZA" "Ceftazidime/avibactam" "standard_dosage" "2 g + 0.5 g" 3 "iv" "over 2 hours" "(2 g ceftazidime + 0.5 g avibactam) x 3 iv over 2 hours" 11
"CTB" "Ceftibuten" "standard_dosage" "0.4 g" 1 "oral" "" "0.4 g x 1 oral" 11
"BPR" "Ceftobiprole" "standard_dosage" "0.5 g" 3 "iv" "over 2 hours" "0.5 g x 3 iv over 2 hours" 11
"CZT" "Ceftolozane/tazobactam" "standard_dosage" "1 g + 0.5 g" 3 "iv" "over 1 hour" "(1 g ceftolozane + 0.5 g tazobactam) x 3 iv over 1 hour" 11
"CZT" "Ceftolozane/tazobactam" "standard_dosage" "2 g + 1 g" 3 "iv" "over 1 hour" "(2 g ceftolozane + 1 g tazobactam) x 3 iv over 1 hour" 11
"CRO" "Ceftriaxone" "high_dosage" "4 g" 1 "iv" "" "4 g x 1 iv" 11
"CRO" "Ceftriaxone" "standard_dosage" "2 g" 1 "iv" "" "2 g x 1 iv" 11
"CXM" "Cefuroxime" "high_dosage" "1.5 g" 3 "iv" "" "1.5 g x 3 iv" 11
"CXM" "Cefuroxime" "standard_dosage" "0.75 g" 3 "iv" "" "0.75 g x 3 iv" 11
"CXM" "Cefuroxime" "high_dosage" "0.5 g" 2 "oral" "" "0.5 g x 2 oral" 11
"CXM" "Cefuroxime" "standard_dosage" "0.25 g" 2 "oral" "" "0.25 g x 2 oral" 11
"CXM" "Cefuroxime" "uncomplicated_uti" "0.25 g" 2 "oral" "" "0.25 g x 2 oral" 11
"LEX" "Cephalexin" "standard_dosage" "0.25-1 g" 2 "oral" "" "0.25-1 g x 2-3 oral" 11
"LEX" "Cephalexin" "uncomplicated_uti" "0.25-1 g" 2 "oral" "" "0.25-1 g x 2-3 oral" 11
"CHL" "Chloramphenicol" "high_dosage" "2 g" 4 "iv" "" "2 g x 4 iv" 11
"CHL" "Chloramphenicol" "standard_dosage" "1 g" 4 "iv" "" "1 g x 4 iv" 11
"CHL" "Chloramphenicol" "high_dosage" "2 g" 4 "oral" "" "2 g x 4 oral" 11
"CHL" "Chloramphenicol" "standard_dosage" "1 g" 4 "oral" "" "1 g x 4 oral" 11
"CIP" "Ciprofloxacin" "high_dosage" "0.4 g" 3 "iv" "" "0.4 g x 3 iv" 11
"CIP" "Ciprofloxacin" "standard_dosage" "0.4 g" 2 "iv" "" "0.4 g x 2 iv" 11
"CIP" "Ciprofloxacin" "high_dosage" "0.75 g" 2 "oral" "" "0.75 g x 2 oral" 11
"CIP" "Ciprofloxacin" "standard_dosage" "0.5 g" 2 "oral" "" "0.5 g x 2 oral" 11
"CLR" "Clarithromycin" "high_dosage" "0.5 g" 2 "oral" "" "0.5 g x 2 oral" 11
"CLR" "Clarithromycin" "standard_dosage" "0.25 g" 2 "oral" "" "0.25 g x 2 oral" 11
"CLI" "Clindamycin" "high_dosage" "0.9 g" 3 "iv" "" "0.9 g x 3 iv" 11
"CLI" "Clindamycin" "standard_dosage" "0.6 g" 3 "iv" "" "0.6 g x 3 iv" 11
"CLI" "Clindamycin" "high_dosage" "0.3 g" 4 "oral" "" "0.3 g x 4 oral" 11
"CLI" "Clindamycin" "standard_dosage" "0.3 g" 2 "oral" "" "0.3 g x 2 oral" 11
"CLO" "Cloxacillin" "high_dosage" "2 g" 6 "iv" "" "2 g x 6 iv" 11
"CLO" "Cloxacillin" "standard_dosage" "1 g" 4 "iv" "" "1 g x 4 iv" 11
"CLO" "Cloxacillin" "high_dosage" "1 g" 4 "oral" "" "1 g x 4 oral" 11
"CLO" "Cloxacillin" "standard_dosage" "0.5 g" 4 "oral" "" "0.5 g x 4 oral" 11
"COL" "Colistin" "standard_dosage" "4.5 MU" 2 "iv" "loading dose of 9 MU" "4.5 MU x 2 iv with a loading dose of 9 MU" 11
"DAL" "Dalbavancin" "standard_dosage" "1 g" 1 "iv" "over 30 minutes on day 8" "1 g x 1 iv over 30 minutes on day 1 If needed, 0.5 g x 1 iv over 30 minutes on day 8" 11
"DAP" "Daptomycin" "standard_dosage" "4 mg/kg" 1 "iv" "" "4 mg/kg x 1 iv" 11
"DAP" "Daptomycin" "standard_dosage" "6 mg/kg" 1 "iv" "" "6 mg/kg x 1 iv" 11
"DFX" "Delafloxacin" "standard_dosage" "0.3 g" 2 "iv" "" "0.3 g x 2 iv" 11
"DFX" "Delafloxacin" "standard_dosage" "0.45 g" 2 "oral" "" "0.45 g x 2 oral" 11
"DIC" "Dicloxacillin" "high_dosage" "2 g" 6 "iv" "" "2 g x 6 iv" 11
"DIC" "Dicloxacillin" "standard_dosage" "1 g" 4 "iv" "" "1 g x 4 iv" 11
"DIC" "Dicloxacillin" "high_dosage" "2 g" 4 "oral" "" "2 g x 4 oral" 11
"DIC" "Dicloxacillin" "standard_dosage" "0.5-1 g" 4 "oral" "" "0.5-1 g x 4 oral" 11
"DOR" "Doripenem" "high_dosage" "1 g" 3 "iv" "over 1 hour" "1 g x 3 iv over 1 hour" 11
"DOR" "Doripenem" "standard_dosage" "0.5 g" 3 "iv" "over 1 hour" "0.5 g x 3 iv over 1 hour" 11
"DOX" "Doxycycline" "high_dosage" "0.2 g" 1 "oral" "" "0.2 g x 1 oral" 11
"DOX" "Doxycycline" "standard_dosage" "0.1 g" 1 "oral" "" "0.1 g x 1 oral" 11
"ERV" "Eravacycline" "standard_dosage" "1 mg/kg" 2 "iv" "" "1 mg/kg x 2 iv" 11
"ETP" "Ertapenem" "standard_dosage" "1 g" 1 "iv" "over 30 minutes" "1 g x 1 iv over 30 minutes" 11
"ERY" "Erythromycin" "high_dosage" "1 g" 4 "iv" "" "1 g x 4 iv" 11
"ERY" "Erythromycin" "standard_dosage" "0.5 g" 2 "iv" "" "0.5 g x 2-4 iv" 11
"ERY" "Erythromycin" "high_dosage" "1 g" 4 "oral" "" "1 g x 4 oral" 11
"ERY" "Erythromycin" "standard_dosage" "0.5 g" 2 "oral" "" "0.5 g x 2-4 oral" 11
"FDX" "Fidaxomicin" "standard_dosage" "0.2 g" 2 "oral" "" "0.2 g x 2 oral" 11
"FLC" "Flucloxacillin" "high_dosage" "2 g" 6 "iv" "" "2 g x 6 iv" 11
"FLC" "Flucloxacillin" "standard_dosage" "2 g" 4 "iv" "" "2 g x 4 iv (or 1 g x 6 iv)" 11
"FLC" "Flucloxacillin" "high_dosage" "1 g" 4 "oral" "" "1 g x 4 oral" 11
"FLC" "Flucloxacillin" "standard_dosage" "1 g" 3 "oral" "" "1 g x 3 oral" 11
"FOS" "Fosfomycin" "high_dosage" "8 g" 3 "iv" "" "8 g x 3 iv" 11
"FOS" "Fosfomycin" "standard_dosage" "4 g" 3 "iv" "" "4 g x 3 iv" 11
"FUS" "Fusidic acid" "high_dosage" "0.5 g" 3 "iv" "" "0.5 g x 3 iv" 11
"FUS" "Fusidic acid" "standard_dosage" "0.5 g" 2 "iv" "" "0.5 g x 2 iv" 11
"FUS" "Fusidic acid" "high_dosage" "0.5 g" 3 "oral" "" "0.5 g x 3 oral" 11
"FUS" "Fusidic acid" "standard_dosage" "0.5 g" 2 "oral" "" "0.5 g x 2 oral" 11
"GEN" "Gentamicin" "standard_dosage" "6-7 mg/kg" 1 "iv" "" "6-7 mg/kg x 1 iv" 11
"IPM" "Imipenem" "high_dosage" "1 g" 4 "iv" "over 30 minutes" "1 g x 4 iv over 30 minutes" 11
"IPM" "Imipenem" "standard_dosage" "0.5 g" 4 "iv" "over 30 minutes" "0.5 g x 4 iv over 30 minutes" 11
"IMR" "Imipenem/relebactam" "standard_dosage" "0.5 g + 0.25 g" 4 "iv" "over 30 minutes" "(0.5 g imipenem + 0.25 g relebactam) x 4 iv over 30 minutes" 11
"IMR" "Imipenem/relebactam" "standard_dosage" "0.5 g + 0.25 g" 4 "iv" "over 30 minutes" "(0.5 g imipenem + 0.25 g relebactam) x 4 iv over 30 minutes" 11
"LMU" "Lefamulin" "standard_dosage" "0.15 g" 2 "iv" "or 0.6 g x 2 oral" "0.15 g x 2 iv or 0.6 g x 2 oral" 11
"LMU" "Lefamulin" "standard_dosage" "0.6 g" 2 "oral" "" "0.6 g x 2 oral" 11
"LVX" "Levofloxacin" "high_dosage" "0.5 g" 2 "iv" "" "0.5 g x 2 iv" 11
"LVX" "Levofloxacin" "standard_dosage" "0.5 g" 1 "iv" "" "0.5 g x 1 iv" 11
"LVX" "Levofloxacin" "high_dosage" "0.5 g" 2 "oral" "" "0.5 g x 2 oral" 11
"LVX" "Levofloxacin" "standard_dosage" "0.5 g" 1 "oral" "" "0.5 g x 1 oral" 11
"LNZ" "Linezolid" "standard_dosage" "0.6 g" 2 "iv" "" "0.6 g x 2 iv" 11
"LNZ" "Linezolid" "standard_dosage" "0.6 g" 2 "oral" "" "0.6 g x 2 oral" 11
"MEM" "Meropenem" "high_dosage" "2 g" 3 "iv" "over 3 hours" "2 g x 3 iv over 3 hours" 11
"MEM" "Meropenem" "standard_dosage" "1 g" 3 "iv" "over 30 minutes" "1 g x 3 iv over 30 minutes" 11
"MEV" "Meropenem/vaborbactam" "standard_dosage" "2 g + 2 g" 3 "iv" "over 3 hours" "(2 g meropenem + 2 g vaborbactam) x 3 iv over 3 hours" 11
"MTR" "Metronidazole" "high_dosage" "0.5 g" 3 "iv" "" "0.5 g x 3 iv" 11
"MTR" "Metronidazole" "standard_dosage" "0.4 g" 3 "iv" "" "0.4 g x 3 iv" 11
"MTR" "Metronidazole" "high_dosage" "0.5 g" 3 "oral" "" "0.5 g x 3 oral" 11
"MTR" "Metronidazole" "standard_dosage" "0.4 g" 3 "oral" "" "0.4 g x 3 oral" 11
"MNO" "Minocycline" "standard_dosage" "0.1 g" 2 "oral" "" "0.1 g x 2 oral" 11
"MFX" "Moxifloxacin" "standard_dosage" "0.4 g" 1 "iv" "" "0.4 g x 1 iv" 11
"MFX" "Moxifloxacin" "standard_dosage" "0.4 g" 1 "oral" "" "0.4 g x 1 oral" 11
"OFX" "Ofloxacin" "high_dosage" "0.4 g" 2 "iv" "" "0.4 g x 2 iv" 11
"OFX" "Ofloxacin" "standard_dosage" "0.2 g" 2 "iv" "" "0.2 g x 2 iv" 11
"OFX" "Ofloxacin" "high_dosage" "0.4 g" 2 "oral" "" "0.4 g x 2 oral" 11
"OFX" "Ofloxacin" "standard_dosage" "0.2 g" 2 "oral" "" "0.2 g x 2 oral" 11
"ORI" "Oritavancin" "standard_dosage" "1.2 g" 1 "iv" "" "1.2 g x 1 (single dose) iv over 3 hours" 11
"OXA" "Oxacillin" "high_dosage" "1 g" 6 "iv" "" "1 g x 6 iv" 11
"OXA" "Oxacillin" "standard_dosage" "1 g" 4 "iv" "" "1 g x 4 iv" 11
"PHN" "Phenoxymethylpenicillin" "standard_dosage" "0.5-2 g" 3 "oral" "" "0.5-2 g x 3-4 oral" 11
"PIP" "Piperacillin" "high_dosage" "4 g" 4 "iv" "" "4 g x 4 iv by extended 3-hour infusion" 11
"PIP" "Piperacillin" "standard_dosage" "4 g" 4 "iv" "" "4 g x 4 iv" 11
"TZP" "Piperacillin/tazobactam" "high_dosage" "4 g + 0.5 g" 4 "iv" "" "(4 g piperacillin + 0.5 g tazobactam) x 4 iv by extended 3-hour infusion" 11
"TZP" "Piperacillin/tazobactam" "standard_dosage" "4 g + 0.5 g" 4 "iv" "" "(4 g piperacillin + 0.5 g tazobactam) x 4 iv or x 3 by extended 4-hour infusion" 11
"QDA" "Quinupristin/dalfopristin" "high_dosage" "7.5 mg/kg" 3 "iv" "" "7.5 mg/kg x 3 iv" 11
"QDA" "Quinupristin/dalfopristin" "standard_dosage" "7.5 mg/kg" 2 "iv" "" "7.5 mg/kg x 2 iv" 11
"RIF" "Rifampicin" "high_dosage" "0.6 g" 2 "iv" "" "0.6 g x 2 iv" 11
"RIF" "Rifampicin" "standard_dosage" "0.6 g" 1 "iv" "" "0.6 g x 1 iv" 11
"RIF" "Rifampicin" "high_dosage" "0.6 g" 2 "oral" "" "0.6 g x 2 oral" 11
"RIF" "Rifampicin" "standard_dosage" "0.6 g" 1 "oral" "" "0.6 g x 1 oral" 11
"RXT" "Roxithromycin" "standard_dosage" "0.15 g" 2 "oral" "" "0.15 g x 2 oral" 11
"SPT" "Spectinomycin" "standard_dosage" "2 g" 1 "im" "" "2 g x 1 im" 11
"TZD" "Tedizolid" "standard_dosage" "0.2 g" 1 "iv" "" "0.2 g x 1 iv" 11
"TZD" "Tedizolid" "standard_dosage" "0.2 g" 1 "oral" "" "0.2 g x 1 oral" 11
"TEC" "Teicoplanin" "high_dosage" "0.8 g" 1 "iv" "" "0.8 g x 1 iv" 11
"TEC" "Teicoplanin" "standard_dosage" "0.4 g" 1 "iv" "" "0.4 g x 1 iv" 11
"TLV" "Telavancin" "standard_dosage" "10 mg/kg" 1 "iv" "over 1 hour" "10 mg/kg x 1 iv over 1 hour" 11
"TLT" "Telithromycin" "standard_dosage" "0.8 g" 1 "oral" "" "0.8 g x 1 oral" 11
"TEM" "Temocillin" "high_dosage" "2 g" 3 "iv" "" "2 g x 3 iv" 11
"TEM" "Temocillin" "standard_dosage" "2 g" 2 "iv" "" "2 g x 2 iv" 11
"TCY" "Tetracycline" "high_dosage" "0.5 g" 4 "oral" "" "0.5 g x 4 oral" 11
"TCY" "Tetracycline" "standard_dosage" "0.25 g" 4 "oral" "" "0.25 g x 4 oral" 11
"TIC" "Ticarcillin" "high_dosage" "3 g" 6 "iv" "" "3 g x 6 iv" 11
"TIC" "Ticarcillin" "standard_dosage" "3 g" 4 "iv" "" "3 g x 4 iv" 11
"TCC" "Ticarcillin/clavulanic acid" "high_dosage" "3 g + 0.1 g" 6 "iv" "" "(3 g ticarcillin + 0.1 g clavulanic acid) x 6 iv" 11
"TCC" "Ticarcillin/clavulanic acid" "standard_dosage" "3 g + 0.1-0.2 g" 4 "iv" "" "(3 g ticarcillin + 0.1-0.2 g clavulanic acid) x 4 iv" 11
"TGC" "Tigecycline" "standard_dosage" "0.1 g" "loading dose followed by 50 mg x 2 iv" "0.1 g loading dose followed by 50 mg x 2 iv" 11
"TOB" "Tobramycin" "standard_dosage" "6-7 mg/kg" 1 "iv" "" "6-7 mg/kg x 1 iv" 11
"SXT" "Trimethoprim/sulfamethoxazole" "high_dosage" "0.24 g + 1.2 g" 2 "oral" "" "(0.24 g trimethoprim + 1.2 g sulfamethoxazole) x 2 oral" 11
"SXT" "Trimethoprim/sulfamethoxazole" "high_dosage" "0.24 g + 1.2 g" 2 "oral" "" "(0.24 g trimethoprim + 1.2 g sulfamethoxazole) x 2 oral or (0.24 g trimethoprim + 1.2 g sulfamethoxazole) x 2 iv" 11
"SXT" "Trimethoprim/sulfamethoxazole" "standard_dosage" "0.16 g + 0.8 g" 2 "oral" "" "(0.16 g trimethoprim + 0.8 g sulfamethoxazole) x 2 oral" 11
"SXT" "Trimethoprim/sulfamethoxazole" "standard_dosage" "0.16 g + 0.8 g" 2 "oral" "" "(0.16 g trimethoprim + 0.8 g sulfamethoxazole) x 2 oral or (0.16 g trimethoprim + 0.8 g sulfamethoxazole) x 2 iv" 11
"SXT" "Trimethoprim/sulfamethoxazole" "uncomplicated_uti" "0.16 g + 0.8 g" 2 "oral" "" "(0.16 g trimethoprim + 0.8 g sulfamethoxazole) x 2 oral" 11
"SXT" "Trimethoprim/sulfamethoxazole" "uncomplicated_uti" "0.16 g + 0.8 g" 2 "oral" "" "(0.16 g trimethoprim + 0.8 g sulfamethoxazole) x 2 oral" 11
"VAN" "Vancomycin" "standard_dosage" "1 g" 2 "iv" "" "1 g x 2 iv or 2 g x 1 by continuous infusion" 11
Binary file not shown.
+116 -1
View File
@@ -1,6 +1,6 @@
# -------------------------------------------------------------------------------------------------------------------------------
# For editing this EUCAST reference file, these values can all be used for targeting antibiotics:
# 'all_betalactams', 'aminoglycosides', 'aminopenicillins', 'carbapenems', 'cephalosporins', 'cephalosporins_1st', 'cephalosporins_2nd', 'cephalosporins_except_CAZ',
# 'all_betalactams', 'aminoglycosides', 'aminopenicillins', 'carbapenems', 'cephalosporins', 'cephalosporins_1st', 'cephalosporins_2nd', 'cephalosporins_3rd', 'cephalosporins_except_CAZ',
# 'fluoroquinolones', 'glycopeptides', 'lincosamides', 'lipoglycopeptides', 'macrolides', 'oxazolidinones', 'polymyxins', 'streptogramins', 'tetracyclines', 'ureidopenicillins',
# and all separate EARS-Net letter codes like 'AMC'. They can be separated by comma: 'AMC, fluoroquinolones'.
# The 'if_mo_property' column can be any column name from the AMR::microorganisms data set, or "genus_species" or "gramstain".
@@ -115,6 +115,115 @@ genus_species is Kingella kingae TCY R DOX R Kingella kingae Breakpoints 10
genus_species is Burkholderia pseudomallei TCY S DOX S Burkholderia pseudomallei Breakpoints 10
genus_species is Burkholderia pseudomallei TCY I DOX I Burkholderia pseudomallei Breakpoints 10
genus_species is Burkholderia pseudomallei TCY R DOX R Burkholderia pseudomallei Breakpoints 10
order is Enterobacterales AMP S AMX S Enterobacterales (Order) Breakpoints 11
order is Enterobacterales AMP I AMX I Enterobacterales (Order) Breakpoints 11
order is Enterobacterales AMP R AMX R Enterobacterales (Order) Breakpoints 11
genus is Staphylococcus PEN, FOX S AMP, AMX, PIP, TIC S Staphylococcus Breakpoints 11
genus is Staphylococcus PEN, FOX R, S OXA, FLC S Staphylococcus Breakpoints 11
genus is Staphylococcus FOX R all_betalactams R Staphylococcus Breakpoints 11
genus_species is Staphylococcus saprophyticus AMP S AMX, AMC, PIP, TZP S Staphylococcus Breakpoints 11
genus is Staphylococcus FOX S carbapenems, cephalosporins_except_CAZ S Staphylococcus Breakpoints 11
genus is Staphylococcus FOX I carbapenems, cephalosporins_except_CAZ I Staphylococcus Breakpoints 11
genus is Staphylococcus FOX R carbapenems, cephalosporins_except_CAZ R Staphylococcus Breakpoints 11
genus is Staphylococcus NOR S CIP, LVX, MFX, OFX S Staphylococcus Breakpoints 11
genus is Staphylococcus ERY S AZM, CLR, RXT S Staphylococcus Breakpoints 11
genus is Staphylococcus ERY I AZM, CLR, RXT I Staphylococcus Breakpoints 11
genus is Staphylococcus ERY R AZM, CLR, RXT R Staphylococcus Breakpoints 11
genus is Staphylococcus TCY S DOX, MNO S Staphylococcus Breakpoints 11
genus is Enterococcus AMP S AMX, AMC, PIP, TZP S Enterococcus Breakpoints 11
genus is Enterococcus AMP I AMX, AMC, PIP, TZP I Enterococcus Breakpoints 11
genus is Enterococcus AMP R AMX, AMC, PIP, TZP R Enterococcus Breakpoints 11
genus is Enterococcus NOR S CIP, LVX S Enterococcus Breakpoints 11
genus is Enterococcus NOR I CIP, LVX I Enterococcus Breakpoints 11
genus is Enterococcus NOR R CIP, LVX R Enterococcus Breakpoints 11
genus_species one_of Streptococcus group A, Streptococcus group B, Streptococcus group C, Streptococcus group G PEN S aminopenicillins, ureidopenicillins, cephalosporins_except_CAZ, carbapenems, FLC, AMC S Streptococcus groups A, B, C, G Breakpoints 11
genus_species like Streptococcus group A, Streptococcus group B, Streptococcus group C, Streptococcus group G PEN I aminopenicillins, ureidopenicillins, cephalosporins_except_CAZ, carbapenems, FLC, AMC I Streptococcus groups A, B, C, G Breakpoints 11
genus_species like Streptococcus group A, Streptococcus group B, Streptococcus group C, Streptococcus group G PEN R aminopenicillins, ureidopenicillins, cephalosporins_except_CAZ, carbapenems, FLC, AMC R Streptococcus groups A, B, C, G Breakpoints 11
genus_species like Streptococcus group A, Streptococcus group B, Streptococcus group C, Streptococcus group G NOR S MFX S Streptococcus groups A, B, C, G Breakpoints 11
genus_species like Streptococcus group A, Streptococcus group B, Streptococcus group C, Streptococcus group G NOR S LVX I Streptococcus groups A, B, C, G Breakpoints 11
genus_species like Streptococcus group A, Streptococcus group B, Streptococcus group C, Streptococcus group G ERY S AZM, CLR, RXT S Streptococcus groups A, B, C, G Breakpoints 11
genus_species like Streptococcus group A, Streptococcus group B, Streptococcus group C, Streptococcus group G ERY I AZM, CLR, RXT I Streptococcus groups A, B, C, G Breakpoints 11
genus_species like Streptococcus group A, Streptococcus group B, Streptococcus group C, Streptococcus group G ERY R AZM, CLR, RXT R Streptococcus groups A, B, C, G Breakpoints 11
genus_species like Streptococcus group A, Streptococcus group B, Streptococcus group C, Streptococcus group G TCY S DOX, MNO S Streptococcus groups A, B, C, G Breakpoints 11
genus_species is Streptococcus pneumoniae PEN S AMP, AMX, AMC, PIP, TZP S Streptococcus pneumoniae Breakpoints 11
genus_species is Streptococcus pneumoniae AMP S AMX, AMC, PIP, TZP S Streptococcus pneumoniae Breakpoints 11
genus_species is Streptococcus pneumoniae AMP I AMX, AMC, PIP, TZP I Streptococcus pneumoniae Breakpoints 11
genus_species is Streptococcus pneumoniae AMP R AMX, AMC, PIP, TZP R Streptococcus pneumoniae Breakpoints 11
genus_species is Streptococcus pneumoniae NOR S MFX S Streptococcus pneumoniae Breakpoints 11
genus_species is Streptococcus pneumoniae NOR S LVX I Streptococcus pneumoniae Breakpoints 11
genus_species is Streptococcus pneumoniae ERY S AZM, CLR, RXT S Streptococcus pneumoniae Breakpoints 11
genus_species is Streptococcus pneumoniae ERY I AZM, CLR, RXT I Streptococcus pneumoniae Breakpoints 11
genus_species is Streptococcus pneumoniae ERY R AZM, CLR, RXT R Streptococcus pneumoniae Breakpoints 11
genus_species is Streptococcus pneumoniae TCY S DOX, MNO S Streptococcus pneumoniae Breakpoints 11
genus_species like ^Streptococcus (anginosus|australis|bovis|constellatus|cristatus|equinus|gallolyticus|gordonii|infantarius|infantis|intermedius|mitis|mutans|oligofermentans|oralis|parasanguinis|peroris|pseudopneumoniae|salivarius|sanguinis|sinensis|sobrinus|thermophilus|vestibularis|viridans)$ PEN S AMP, AMX, AMC, PIP, TZP S Viridans group streptococci Breakpoints 11
genus_species like ^Streptococcus (anginosus|australis|bovis|constellatus|cristatus|equinus|gallolyticus|gordonii|infantarius|infantis|intermedius|mitis|mutans|oligofermentans|oralis|parasanguinis|peroris|pseudopneumoniae|salivarius|sanguinis|sinensis|sobrinus|thermophilus|vestibularis|viridans)$ AMP S AMX, AMC, PIP, TZP S Viridans group streptococci Breakpoints 11
genus_species like ^Streptococcus (anginosus|australis|bovis|constellatus|cristatus|equinus|gallolyticus|gordonii|infantarius|infantis|intermedius|mitis|mutans|oligofermentans|oralis|parasanguinis|peroris|pseudopneumoniae|salivarius|sanguinis|sinensis|sobrinus|thermophilus|vestibularis|viridans)$ AMP I AMX, AMC, PIP, TZP I Viridans group streptococci Breakpoints 11
genus_species like ^Streptococcus (anginosus|australis|bovis|constellatus|cristatus|equinus|gallolyticus|gordonii|infantarius|infantis|intermedius|mitis|mutans|oligofermentans|oralis|parasanguinis|peroris|pseudopneumoniae|salivarius|sanguinis|sinensis|sobrinus|thermophilus|vestibularis|viridans)$ AMP R AMX, AMC, PIP, TZP R Viridans group streptococci Breakpoints 11
genus_species is Haemophilus influenzae AMP S AMX, PIP S Haemophilus influenzae Breakpoints 11
genus_species is Haemophilus influenzae AMP I AMX, PIP I Haemophilus influenzae Breakpoints 11
genus_species is Haemophilus influenzae AMP R AMX, PIP R Haemophilus influenzae Breakpoints 11
genus_species is Haemophilus influenzae PEN S AMP, AMX, AMC, PIP, TZP S Haemophilus influenzae Breakpoints 11
genus_species is Haemophilus influenzae AMC S TZP S Haemophilus influenzae Breakpoints 11
genus_species is Haemophilus influenzae AMC I TZP I Haemophilus influenzae Breakpoints 11
genus_species is Haemophilus influenzae AMC R TZP R Haemophilus influenzae Breakpoints 11
genus_species is Haemophilus influenzae NAL S CIP, LVX, MFX, OFX S Haemophilus influenzae Breakpoints 11
genus_species is Haemophilus influenzae TCY S DOX, MNO S Haemophilus influenzae Breakpoints 11
genus_species is Moraxella catarrhalis AMC S TZP S Moraxella catarrhalis Breakpoints 11
genus_species is Moraxella catarrhalis AMC I TZP I Moraxella catarrhalis Breakpoints 11
genus_species is Moraxella catarrhalis AMC R TZP R Moraxella catarrhalis Breakpoints 11
genus_species is Moraxella catarrhalis NAL S CIP, LVX, MFX, OFX S Moraxella catarrhalis Breakpoints 11
genus_species is Moraxella catarrhalis ERY S AZM, CLR, RXT S Moraxella catarrhalis Breakpoints 11
genus_species is Moraxella catarrhalis ERY I AZM, CLR, RXT I Moraxella catarrhalis Breakpoints 11
genus_species is Moraxella catarrhalis ERY R AZM, CLR, RXT R Moraxella catarrhalis Breakpoints 11
genus_species is Moraxella catarrhalis TCY S DOX, MNO S Moraxella catarrhalis Breakpoints 11
genus one_of Actinomyces, Bifidobacterium, Clostridium, Cutibacterium, Eggerthella, Eubacterium, Lactobacillus, Propionibacterium PEN S AMP, AMX, PIP, TZP, TIC S Anaerobic Gram-positives Breakpoints 11
genus one_of Actinomyces, Bifidobacterium, Clostridium, Cutibacterium, Eggerthella, Eubacterium, Lactobacillus, Propionibacterium PEN I AMP, AMX, PIP, TZP, TIC I Anaerobic Gram-positives Breakpoints 11
genus one_of Actinomyces, Bifidobacterium, Clostridium, Cutibacterium, Eggerthella, Eubacterium, Lactobacillus, Propionibacterium PEN R AMP, AMX, PIP, TZP, TIC R Anaerobic Gram-positives Breakpoints 11
genus one_of Bacteroides, Bilophila , Fusobacterium, Mobiluncus, Porphyromonas, Prevotella PEN S AMP, AMX, PIP, TZP, TIC S Anaerobic Gram-negatives Breakpoints 11
genus one_of Bacteroides, Bilophila , Fusobacterium, Mobiluncus, Porphyromonas, Prevotella PEN I AMP, AMX, PIP, TZP, TIC I Anaerobic Gram-negatives Breakpoints 11
genus one_of Bacteroides, Bilophila , Fusobacterium, Mobiluncus, Porphyromonas, Prevotella PEN R AMP, AMX, PIP, TZP, TIC R Anaerobic Gram-negatives Breakpoints 11
genus_species is Pasteurella multocida PEN S AMP, AMX S Pasteurella multocida Breakpoints 11
genus_species is Pasteurella multocida PEN I AMP, AMX I Pasteurella multocida Breakpoints 11
genus_species is Pasteurella multocida PEN R AMP, AMX R Pasteurella multocida Breakpoints 11
genus_species is Campylobacter coli ERY S AZM, CLR S Campylobacter coli Breakpoints 11
genus_species is Campylobacter coli ERY I AZM, CLR I Campylobacter coli Breakpoints 11
genus_species is Campylobacter coli ERY R AZM, CLR R Campylobacter coli Breakpoints 11
genus_species is Campylobacter coli TCY S DOX S Campylobacter coli Breakpoints 11
genus_species is Campylobacter coli TCY I DOX I Campylobacter coli Breakpoints 11
genus_species is Campylobacter coli TCY R DOX R Campylobacter coli Breakpoints 11
genus_species is Campylobacter jejuni ERY S AZM, CLR S Campylobacter jejuni Breakpoints 11
genus_species is Campylobacter jejuni ERY I AZM, CLR I Campylobacter jejuni Breakpoints 11
genus_species is Campylobacter jejuni ERY R AZM, CLR R Campylobacter jejuni Breakpoints 11
genus_species is Campylobacter jejuni TCY S DOX S Campylobacter jejuni Breakpoints 11
genus_species is Campylobacter jejuni TCY I DOX I Campylobacter jejuni Breakpoints 11
genus_species is Campylobacter jejuni TCY R DOX R Campylobacter jejuni Breakpoints 11
genus_species is Aerococcus sanguinicola NOR S fluoroquinolones S Aerococcus sanguinicola Breakpoints 11
genus_species is Aerococcus sanguinicola NOR I fluoroquinolones I Aerococcus sanguinicola Breakpoints 11
genus_species is Aerococcus sanguinicola NOR R fluoroquinolones R Aerococcus sanguinicola Breakpoints 11
genus_species is Aerococcus sanguinicola CIP S LVX S Aerococcus sanguinicola Breakpoints 11
genus_species is Aerococcus sanguinicola CIP I LVX I Aerococcus sanguinicola Breakpoints 11
genus_species is Aerococcus sanguinicola CIP R LVX R Aerococcus urinae Breakpoints 11
genus_species is Aerococcus urinae NOR S fluoroquinolones S Aerococcus urinae Breakpoints 11
genus_species is Aerococcus urinae NOR I fluoroquinolones I Aerococcus urinae Breakpoints 11
genus_species is Aerococcus urinae NOR R fluoroquinolones R Aerococcus urinae Breakpoints 11
genus_species is Aerococcus urinae CIP S LVX S Aerococcus urinae Breakpoints 11
genus_species is Aerococcus urinae CIP I LVX I Aerococcus urinae Breakpoints 11
genus_species is Aerococcus urinae CIP R LVX R Aerococcus urinae Breakpoints 11
genus_species is Kingella kingae PEN S AMP, AMX S Kingella kingae Breakpoints 11
genus_species is Kingella kingae PEN I AMP, AMX I Kingella kingae Breakpoints 11
genus_species is Kingella kingae PEN R AMP, AMX R Kingella kingae Breakpoints 11
genus_species is Kingella kingae ERY S AZM, CLR S Kingella kingae Breakpoints 11
genus_species is Kingella kingae ERY I AZM, CLR I Kingella kingae Breakpoints 11
genus_species is Kingella kingae ERY R AZM, CLR R Kingella kingae Breakpoints 11
genus_species is Kingella kingae TCY S DOX S Kingella kingae Breakpoints 11
genus_species is Kingella kingae TCY I DOX I Kingella kingae Breakpoints 11
genus_species is Kingella kingae TCY R DOX R Kingella kingae Breakpoints 11
genus_species is Burkholderia pseudomallei TCY S DOX S Burkholderia pseudomallei Breakpoints 11
genus_species is Burkholderia pseudomallei TCY I DOX I Burkholderia pseudomallei Breakpoints 11
genus_species is Burkholderia pseudomallei TCY R DOX R Burkholderia pseudomallei Breakpoints 11
genus is Bacillus NOR S fluoroquinolones S Bacillus Breakpoints 11 added in 11
genus is Bacillus NOR I fluoroquinolones I Bacillus Breakpoints 11 added in 11
genus is Bacillus NOR R fluoroquinolones R Bacillus Breakpoints 11 added in 11
order is Enterobacterales PEN, glycopeptides, FUS, macrolides, LIN, streptogramins, RIF, DAP, LNZ R Table 01: Intrinsic resistance in Enterobacterales (at the time: Enterobacteriaceae) Expert Rules 3.1
fullname like ^Citrobacter (koseri|amalonaticus|sedlakii|farmeri|rodentium) aminopenicillins, TIC R Table 01: Intrinsic resistance in Enterobacterales (at the time: Enterobacteriaceae) Expert Rules 3.1
fullname like ^Citrobacter (freundii|braakii|murliniae|werkmanii|youngae) aminopenicillins, AMC, CZO, FOX R Table 01: Intrinsic resistance in Enterobacterales (at the time: Enterobacteriaceae) Expert Rules 3.1
@@ -300,3 +409,9 @@ genus_species is Moraxella catarrhalis NAL S fluoroquinolones S Expert Rules on
genus_species is Moraxella catarrhalis NAL R fluoroquinolones R Expert Rules on Moraxella catarrhalis Expert Rules 3.2
genus is Campylobacter ERY S CLR, AZM S Expert Rules on Campylobacter Expert Rules 3.2
genus_species is Campylobacter ERY R CLR, AZM R Expert Rules on Campylobacter Expert Rules 3.2
fullname like ^(Enterobacter|Klebsiella aerogenes|Citrobacter braakii|Citrobacter freundii|Citrobacter gillenii|Citrobacter murliniae|Citrobacter rodenticum|Citrobacter sedlakii|Citrobacter werkmanii|Citrobacter youngae|Hafnia alvei|Serratia|Morganella morganii|Providencia) CTX S CTX, CRO, CAZ Expert Rules on Enterobacterales (AmpC de-repressed cephalosporins) Expert Rules 3.2 This is rule 3 and 4 of EUCAST Expert Rules v3.2 on Enterobacterales, result will be set with the 'ampc_derepressed_cephalosporins' argument
fullname like ^(Enterobacter|Klebsiella aerogenes|Citrobacter braakii|Citrobacter freundii|Citrobacter gillenii|Citrobacter murliniae|Citrobacter rodenticum|Citrobacter sedlakii|Citrobacter werkmanii|Citrobacter youngae|Hafnia alvei|Serratia|Morganella morganii|Providencia) CRO S CTX, CRO, CAZ Expert Rules on Enterobacterales (AmpC de-repressed cephalosporins) Expert Rules 3.2 This is rule 3 and 4 of EUCAST Expert Rules v3.2 on Enterobacterales, result will be set with the 'ampc_derepressed_cephalosporins' argument
fullname like ^(Enterobacter|Klebsiella aerogenes|Citrobacter braakii|Citrobacter freundii|Citrobacter gillenii|Citrobacter murliniae|Citrobacter rodenticum|Citrobacter sedlakii|Citrobacter werkmanii|Citrobacter youngae|Hafnia alvei|Serratia|Morganella morganii|Providencia) CAZ S CTX, CRO, CAZ Expert Rules on Enterobacterales (AmpC de-repressed cephalosporins) Expert Rules 3.2 This is rule 3 and 4 of EUCAST Expert Rules v3.2 on Enterobacterales, result will be set with the 'ampc_derepressed_cephalosporins' argument
fullname like ^(Enterobacter|Klebsiella aerogenes|Citrobacter braakii|Citrobacter freundii|Citrobacter gillenii|Citrobacter murliniae|Citrobacter rodenticum|Citrobacter sedlakii|Citrobacter werkmanii|Citrobacter youngae|Hafnia alvei|Serratia|Morganella morganii|Providencia) CTX I CTX, CRO, CAZ Expert Rules on Enterobacterales (AmpC de-repressed cephalosporins) Expert Rules 3.2 This is rule 3 and 4 of EUCAST Expert Rules v3.2 on Enterobacterales, result will be set with the 'ampc_derepressed_cephalosporins' argument
fullname like ^(Enterobacter|Klebsiella aerogenes|Citrobacter braakii|Citrobacter freundii|Citrobacter gillenii|Citrobacter murliniae|Citrobacter rodenticum|Citrobacter sedlakii|Citrobacter werkmanii|Citrobacter youngae|Hafnia alvei|Serratia|Morganella morganii|Providencia) CRO I CTX, CRO, CAZ Expert Rules on Enterobacterales (AmpC de-repressed cephalosporins) Expert Rules 3.2 This is rule 3 and 4 of EUCAST Expert Rules v3.2 on Enterobacterales, result will be set with the 'ampc_derepressed_cephalosporins' argument
fullname like ^(Enterobacter|Klebsiella aerogenes|Citrobacter braakii|Citrobacter freundii|Citrobacter gillenii|Citrobacter murliniae|Citrobacter rodenticum|Citrobacter sedlakii|Citrobacter werkmanii|Citrobacter youngae|Hafnia alvei|Serratia|Morganella morganii|Providencia) CAZ I CTX, CRO, CAZ Expert Rules on Enterobacterales (AmpC de-repressed cephalosporins) Expert Rules 3.2 This is rule 3 and 4 of EUCAST Expert Rules v3.2 on Enterobacterales, result will be set with the 'ampc_derepressed_cephalosporins' argument
Can't render this file because it contains an unexpected character in line 6 and column 96.
+3 -3
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
# last updated: 20 January 2020 - Loinc_2.67
+3 -3
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
# ------------------------------------------------
+42 -38
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,11 +20,12 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
library(openxlsx)
library(dplyr)
library(tidyr)
library(cleaner)
library(AMR)
@@ -32,9 +33,18 @@ library(AMR)
read_EUCAST <- function(sheet, file, guideline_name) {
message("Getting sheet ", sheet)
message("\nGetting sheet: ", sheet)
sheet.bak <- sheet
uncertainties <- NULL
add_uncertainties <- function(old, new) {
if (is.null(old)) {
new
} else {
bind_rows(old, new)
}
}
raw_data <- read.xlsx(xlsxFile = file,
sheet = sheet,
colNames = FALSE,
@@ -42,6 +52,12 @@ read_EUCAST <- function(sheet, file, guideline_name) {
skipEmptyCols = FALSE,
fillMergedCells = TRUE,
na.strings = c("", "-", "NA", "IE", "IP"))
probable_rows <- suppressWarnings(raw_data %>% mutate_all(as.double) %>% summarise_all(~sum(!is.na(.))) %>% unlist() %>% max())
if (probable_rows == 0) {
message("NO ROWS FOUND")
message("------------------------")
return(NULL)
}
# in the info header in the Excel file, EUCAST mentions which genera are targeted
if (sheet %like% "anaerob.*Gram.*posi") {
@@ -69,7 +85,8 @@ read_EUCAST <- function(sheet, file, guideline_name) {
} else if (sheet %like% "PK.*PD") {
sheet <- "UNKNOWN"
}
mo_sheet <- paste0(as.mo(unlist(strsplit(sheet, "_"))), collapse = "|")
mo_sheet <- paste0(suppressMessages(as.mo(unlist(strsplit(sheet, "_")))), collapse = "|")
if (!is.null(mo_uncertainties())) uncertainties <- add_uncertainties(uncertainties, mo_uncertainties())
set_columns_names <- function(x, cols) {
colnames(x) <- cols[1:length(colnames(x))]
@@ -80,7 +97,8 @@ read_EUCAST <- function(sheet, file, guideline_name) {
for (i in seq_len(length(x))) {
y <- trimws(unlist(strsplit(x[i], "(,|and)")))
y <- trimws(gsub("[(].*[)]", "", y))
y <- suppressWarnings(as.mo(y, allow_uncertain = FALSE))
y <- suppressWarnings(suppressMessages(as.mo(y, allow_uncertain = FALSE)))
if (!is.null(mo_uncertainties())) uncertainties <<- add_uncertainties(uncertainties, mo_uncertainties())
y <- y[!is.na(y) & y != "UNKNOWN"]
x[i] <- paste(y, collapse = "|")
}
@@ -153,7 +171,8 @@ read_EUCAST <- function(sheet, file, guideline_name) {
mutate(drug = gsub(" ?[(, ].*$", "", drug),
drug = gsub("[1-9]+$", "", drug),
ab = as.ab(drug)) %>%
select(ab, mo, everything(), -drug)
select(ab, mo, everything(), -drug) %>%
as.data.frame(stringsAsFactors = FALSE)
# new row for every different MO mentioned
for (i in 1:nrow(cleaned)) {
@@ -162,7 +181,7 @@ read_EUCAST <- function(sheet, file, guideline_name) {
mo_vect <- unlist(strsplit(mo, "|", fixed = TRUE))
cleaned[i, "mo"] <- mo_vect[1]
for (j in seq_len(length(mo_vect))) {
cleaned <- bind_rows(cleaned, cleaned[i ,])
cleaned <- bind_rows(cleaned, cleaned[i , , drop = FALSE])
cleaned[nrow(cleaned), "mo"] <- mo_vect[j]
}
}
@@ -190,41 +209,26 @@ read_EUCAST <- function(sheet, file, guideline_name) {
ref_tbl = sheet.bak,
disk_dose = ifelse(!is.na(disk_dose), paste0(disk_dose, "ug"), NA_character_),
breakpoint_S,
breakpoint_R)
breakpoint_R) %>%
as.data.frame(stringsAsFactors = FALSE)
if (!is.null(uncertainties)) {
print(uncertainties %>% distinct(input, mo, .keep_all = TRUE))
}
message("Estimated: ", probable_rows, ", gained: ", cleaned %>% count(ab) %>% nrow())
message("------------------------")
cleaned
}
sheets_to_analyse <- c("Enterobacterales",
"Pseudomonas",
"S.maltophilia",
"Acinetobacter",
"Staphylococcus",
"Enterococcus",
"Streptococcus A,B,C,G",
"S.pneumoniae",
"Viridans group streptococci",
"H.influenzae",
"M.catarrhalis",
"N.gonorrhoeae",
"N.meningitidis",
"Anaerobes, Grampositive",
"C.difficile",
"Anaerobes, Gramnegative",
"H.pylori",
"L.monocytogenes",
"P.multocida",
"C.jejuni_C.coli",
"Corynebacterium",
"A.sanguinicola_A.urinae",
"K.kingae",
"Aeromonas",
"B.pseudomallei",
"M.tuberculosis",
"PK PD breakpoints")
file <- "data-raw/v_10.0_Breakpoint_Tables.xlsx"
guideline_name <- "EUCAST 2020"
# Actual import -----------------------------------------------------------
file <- "data-raw/v_11.0_Breakpoint_Tables.xlsx"
sheets <- readxl::excel_sheets(file)
guideline_name <- "EUCAST 2021"
sheets_to_analyse <- sheets[!sheets %in% c("Content", "Changes", "Notes", "Guidance", "Dosages", "Technical uncertainty", "Topical agents")]
# takes the longest time:
new_EUCAST <- read_EUCAST(sheet = sheets_to_analyse[1],
+17 -3
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
library(dplyr)
@@ -606,6 +606,20 @@ antibiotics <- antibiotics %>%
TRUE ~ group))
antibiotics[which(antibiotics$ab %in% c("CYC", "LNZ", "THA", "TZD")), "group"] <- "Oxazolidinones"
# add pretomanid
antibiotics <- antibiotics %>%
mutate(ab = as.character(ab)) %>%
bind_rows(antibiotics %>%
mutate(ab = as.character(ab)) %>%
filter(ab == "SMF") %>%
mutate(ab = "PMD",
atc = "J04AK08",
cid = 456199,
name = "Pretomanid",
abbreviations = list(""),
oral_ddd = NA_real_))
# update DDDs from WHOCC website
ddd_oral <- double(length = nrow(antibiotics))
ddd_iv <- double(length = nrow(antibiotics))
+3 -3
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
# get all data from the WHOCC website
+159
View File
@@ -0,0 +1,159 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
# #
# This R package is free software; you can freely use and distribute #
# it for both personal and commercial purposes under the terms of the #
# GNU General Public License version 2.0 (GNU GPL-2), as published by #
# the Free Software Foundation. #
# We created this package for both routine data analysis and academic #
# research and it was publicly released in the hope that it will be #
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
library(dplyr)
library(readxl)
library(cleaner)
# URL:
# https://www.eucast.org/fileadmin/src/media/PDFs/EUCAST_files/Breakpoint_tables/Dosages_v_11.0_Breakpoint_Tables.pdf
# download the PDF file, open in Acrobat Pro and export as Excel workbook
breakpoints_version <- 11
dosage_source <- read_excel("data-raw/Dosages_v_11.0_Breakpoint_Tables.xlsx", skip = 5, na = "None") %>%
format_names(snake_case = TRUE, penicillins = "drug") %>%
filter(!tolower(standard_dosage) %in% c("standard dosage_source", "under review")) %>%
filter(!is.na(standard_dosage)) %>%
# keep only one drug in the table
arrange(desc(drug)) %>%
mutate(drug = gsub("(.*) ([(]|iv|oral).*", "\\1", drug)) %>%
#distinct(drug, .keep_all = TRUE) %>%
arrange(drug) %>%
mutate(ab = as.ab(drug),
ab_name = ab_name(ab, language = NULL))
dosage_source <- bind_rows(
# oral
dosage_source %>%
filter(standard_dosage %like% " oral") %>%
mutate(standard_dosage = gsub("oral.*", "oral", standard_dosage),
high_dosage = if_else(high_dosage %like% "oral",
gsub("oral.*", "oral", high_dosage),
NA_character_)),
# iv
dosage_source %>%
filter(standard_dosage %like% " iv") %>%
mutate(standard_dosage = gsub(".* or ", "", standard_dosage),
high_dosage = if_else(high_dosage %like% "( or | iv)",
gsub(".* or ", "", high_dosage),
NA_character_)),
# im
dosage_source %>%
filter(standard_dosage %like% " im")
) %>%
arrange(drug)
get_dosage_lst <- function(col_data) {
standard <- col_data %>%
# remove new lines
gsub(" ?(\n|\t)+ ?", " ", .) %>%
# keep only the first suggestion, replace all after 'or' and more informative texts
gsub("(.*?) (or|with|loading|depending|over|by) .*", "\\1", .) %>%
# remove (1 MU)
gsub(" [(][0-9] [A-Z]+[)]", "", .) %>%
# remove parentheses
gsub("[)(]", "", .) %>%
# remove drug names
gsub(" [a-z]{5,99}( |$)", " ", .) %>%
gsub(" [a-z]{5,99}( |$)", " ", .) %>%
gsub(" (acid|dose)", "", .)# %>%
# keep lowest value only (25-30 mg -> 25 mg)
# gsub("[-].*? ", " ", .)
dosage_lst <- lapply(strsplit(standard, " x "),
function(x) {
dose <- x[1]
if (dose %like% "under") {
dose <- NA_character_
}
admin <- x[2]
list(
dose = trimws(dose),
dose_times = gsub("^([0-9.]+).*", "\\1", admin),
administration = clean_character(admin),
notes = "",
original_txt = ""
)
})
for (i in seq_len(length(col_data))) {
dosage_lst[[i]]$original_txt <- gsub("\n", " ", col_data[i])
if (col_data[i] %like% " (or|with|loading|depending|over) ") {
dosage_lst[[i]]$notes <- gsub("\n", " ", gsub(".* ((or|with|loading|depending|over) .*)", "\\1", col_data[i]))
}
}
dosage_lst
}
standard <- get_dosage_lst(dosage_source$standard_dosage)
high <- get_dosage_lst(dosage_source$high_dosage)
uti <- get_dosage_lst(dosage_source$uncomplicated_uti)
dosage <- bind_rows(
# standard dose
data.frame(
ab = dosage_source$ab,
name = dosage_source$ab_name,
type = "standard_dosage",
dose = sapply(standard, function(x) x$dose),
dose_times = sapply(standard, function(x) x$dose_times),
administration = sapply(standard, function(x) x$administration),
notes = sapply(standard, function(x) x$notes),
original_txt = sapply(standard, function(x) x$original_txt),
stringsAsFactors = FALSE
),
# high dose
data.frame(
ab = dosage_source$ab,
name = dosage_source$ab_name,
type = "high_dosage",
dose = sapply(high, function(x) x$dose),
dose_times = sapply(high, function(x) x$dose_times),
administration = sapply(high, function(x) x$administration),
notes = sapply(high, function(x) x$notes),
original_txt = sapply(high, function(x) x$original_txt),
stringsAsFactors = FALSE
),
# UTIs
data.frame(
ab = dosage_source$ab,
name = dosage_source$ab_name,
type = "uncomplicated_uti",
dose = sapply(uti, function(x) x$dose),
dose_times = sapply(uti, function(x) x$dose_times),
administration = sapply(uti, function(x) x$administration),
notes = sapply(uti, function(x) x$notes),
original_txt = sapply(uti, function(x) x$original_txt),
stringsAsFactors = FALSE
)) %>%
mutate(eucast_version = breakpoints_version,
dose_times = as.integer(dose_times),
administration = gsub("([a-z]+) .*", "\\1", administration)) %>%
arrange(name, administration, type) %>%
filter(!is.na(dose), dose != ".") %>%
as.data.frame(stringsAsFactors = FALSE)
rownames(dosage) <- NULL
usethis::use_data(dosage, internal = FALSE, overwrite = TRUE, version = 2)
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
patients <- unlist(lapply(LETTERS, paste0, 1:10))
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,10 +20,11 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
library(AMR)
library(dplyr)
int_resis <- data.frame(microorganism = microorganisms$mo, stringsAsFactors = FALSE)
for (i in seq_len(nrow(antibiotics))) {
int_resis$new <- as.rsi("S")
@@ -45,3 +46,6 @@ int_resis2$microorganism <- mo_name(int_resis2$microorganism, language = NULL)
intrinsic_resistant <- as.data.frame(int_resis2, stringsAsFactors = FALSE)
usethis::use_data(intrinsic_resistant, internal = FALSE, overwrite = TRUE, version = 2, compress = "xz")
rm(intrinsic_resistant)
# AFTER THIS:
# DO NOT FORGET TO UPDATE THE VERSION NUMBER IN mo_is_intrinsic_resistant()
+11 -9
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,25 +20,27 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
# Reproduction of the `microorganisms` data set
# Data retrieved from the Catalogue of Life (CoL) through the Encyclopaedia of Life:
# https://opendata.eol.org/dataset/catalogue-of-life/
# Data retrieved from the Catalogue of Life (CoL):
# https://download.catalogueoflife.org/col/monthly/life/
# (download latest dwca, such as https://download.catalogueoflife.org/col/monthly/2020-12-01_dwca.zip)
# Data retrieved from the Global Biodiversity Information Facility (GBIF):
# https://doi.org/10.15468/rffz4x
#
# And from the Leibniz Institute: German Collection of Microorganisms and Cell Cultures (DSMZ)
# (register first at https://bacdive.dsmz.de/api/pnu/registration/register/ and use API as done below)
# And from the List of Prokaryotic names with Standing in Nomenclature (LPSN)
# (register first) https://lpsn.dsmz.de/downloads
# download the latest CSV file.
library(dplyr)
library(AMR)
# also needed: data.table, httr, jsonlite, cleaner, stringr
# unzip and extract taxa.txt (both around 1.5 GB, 3.7-3.9M rows) from Col and GBIF, then:
data_col_raw <- data.table::fread("data-raw/taxon.tab", quote = "")
data_col_raw <- data.table::fread("data-raw/taxon.tsv", quote = "")
data_gbif <- data.table::fread("data-raw/taxa.txt", quote = "")
# merge the two
@@ -925,7 +927,7 @@ usethis::use_data(rsi_translation, overwrite = TRUE, version = 2)
usethis::use_data(microorganisms.codes, overwrite = TRUE, version = 2)
saveRDS(microorganisms.translation, file = "data-raw/microorganisms.translation.rds", version = 2)
# to save microorganisms.translation internally to the package
source("data-raw/internals.R")
source("data-raw/_internals.R")
# load new data sets again
devtools::load_all(".")
+4
View File
@@ -75,3 +75,7 @@ contents <- gsub("pm_distinct <- function(.data, ..., .keep_all = FALSE)", "pm_d
contents <- contents[!grepl("summarize", contents)]
writeLines(contents, "R/aa_helper_pm_functions.R")
# after this, comment out:
# pm_left_join() since we use a faster version
# pm_group_split() since we don't use it and it relies on R 3.5.0 for the use of ...length(), which is hard to support with C++ code
@@ -77,6 +77,7 @@ clsi_general <- read_tsv("data-raw/DRGLST.txt") %>%
# add new EUCAST with read_EUCAST.R
# 2020-04-14 did that now for 2019 and 2020
rsi_trans <- rsi_trans %>%
filter(guideline != "EUCAST 2019") %>%
bind_rows(new_EUCAST) %>%
@@ -88,6 +89,17 @@ rsi_trans <- rsi_trans %>%
ab = as.ab(ab)) %>%
arrange(desc(guideline), ab, mo, method)
# 2021-01-12 did that now for 2021
rsi_trans <- rsi_trans %>%
mutate(mo = as.character(mo)) %>%
bind_rows(new_EUCAST) %>%
mutate(uti = site %like% "(UTI|urinary)") %>%
as.data.frame(stringsAsFactors = FALSE) %>%
# force classes again
mutate(mo = as.mo(mo),
ab = as.ab(ab)) %>%
arrange(desc(guideline), ab, mo, method)
# save to package
rsi_translation <- rsi_trans
usethis::use_data(rsi_translation, overwrite = TRUE)
+1 -1
View File
@@ -1 +1 @@
c589396a6728f7c72def07b4dfb35e28
f816b536ddd71d00e1adcdaba97d0329
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
+3 -3
View File
@@ -1,12 +1,12 @@
# ==================================================================== #
# TITLE #
# Antimicrobial Resistance (AMR) Analysis for R #
# Antimicrobial Resistance (AMR) Data Analysis for R #
# #
# SOURCE #
# https://github.com/msberends/AMR #
# #
# LICENCE #
# (c) 2018-2020 Berends MS, Luz CF et al. #
# (c) 2018-2021 Berends MS, Luz CF et al. #
# Developed at the University of Groningen, the Netherlands, in #
# collaboration with non-profit organisations Certe Medical #
# Diagnostics & Advice, and University Medical Center Groningen. #
@@ -20,7 +20,7 @@
# useful, but it comes WITHOUT ANY WARRANTY OR LIABILITY. #
# #
# Visit our website for the full manual and a complete tutorial about #
# how to conduct AMR analysis: https://msberends.github.io/AMR/ #
# how to conduct AMR data analysis: https://msberends.github.io/AMR/ #
# ==================================================================== #
library(AMR)
+412 -401
View File
@@ -1,401 +1,412 @@
lang pattern replacement fixed ignore.case
de Coagulase-negative Staphylococcus Koagulase-negative Staphylococcus FALSE FALSE
de Coagulase-positive Staphylococcus Koagulase-positive Staphylococcus FALSE FALSE
de Beta-haemolytic Streptococcus Beta-hämolytischer Streptococcus FALSE FALSE
de unknown Gram-negatives unbekannte Gramnegativen FALSE FALSE
de unknown Gram-positives unbekannte Grampositiven FALSE FALSE
de unknown name unbekannte Name FALSE FALSE
de unknown kingdom unbekanntes Reich FALSE FALSE
de unknown phylum unbekannter Stamm FALSE FALSE
de unknown class unbekannte Klasse FALSE FALSE
de unknown order unbekannte Ordnung FALSE FALSE
de unknown family unbekannte Familie FALSE FALSE
de unknown genus unbekannte Gattung FALSE FALSE
de unknown species unbekannte Art FALSE FALSE
de unknown subspecies unbekannte Unterart FALSE FALSE
de unknown rank unbekannter Rang FALSE FALSE
de CoNS KNS TRUE FALSE
de CoPS KPS TRUE FALSE
de Gram-negative Gramnegativ FALSE FALSE
de Gram-positive Grampositiv FALSE FALSE
de Bacteria Bakterien FALSE FALSE
de Fungi Hefen/Pilze FALSE FALSE
de Protozoa Protozoen FALSE FALSE
de biogroup Biogruppe FALSE FALSE
de biotype Biotyp FALSE FALSE
de vegetative vegetativ FALSE FALSE
de ([([ ]*?)group \\1Gruppe FALSE FALSE
de ([([ ]*?)Group \\1Gruppe FALSE FALSE
de no .*growth keine? .*wachstum FALSE TRUE
de no|not keine? FALSE TRUE
nl Coagulase-negative Staphylococcus Coagulase-negatieve Staphylococcus FALSE FALSE
nl Coagulase-positive Staphylococcus Coagulase-positieve Staphylococcus FALSE FALSE
nl Beta-haemolytic Streptococcus Beta-hemolytische Streptococcus FALSE FALSE
nl unknown Gram-negatives onbekende Gram-negatieven FALSE FALSE
nl unknown Gram-positives onbekende Gram-positieven FALSE FALSE
nl unknown name onbekende naam FALSE FALSE
nl unknown kingdom onbekend koninkrijk FALSE FALSE
nl unknown phylum onbekend fylum FALSE FALSE
nl unknown class onbekende klasse FALSE FALSE
nl unknown order onbekende orde FALSE FALSE
nl unknown family onbekende familie FALSE FALSE
nl unknown genus onbekend geslacht FALSE FALSE
nl unknown species onbekende soort FALSE FALSE
nl unknown subspecies onbekende ondersoort FALSE FALSE
nl unknown rank onbekende rang FALSE FALSE
nl CoNS CNS TRUE FALSE
nl CoPS CPS TRUE FALSE
nl Gram-negative Gram-negatief FALSE FALSE
nl Gram-positive Gram-positief FALSE FALSE
nl Bacteria Bacteriën FALSE FALSE
nl Fungi Schimmels/gisten FALSE FALSE
nl Protozoa protozoën FALSE FALSE
nl biogroup biogroep FALSE FALSE
nl vegetative vegetatief FALSE FALSE
nl ([([ ]*?)group \\1groep FALSE FALSE
nl ([([ ]*?)Group \\1Groep FALSE FALSE
nl antibiotic antibioticum FALSE FALSE
nl Antibiotic Antibioticum FALSE FALSE
nl Drug Middel FALSE FALSE
nl drug middel FALSE FALSE
nl no .*growth geen .*groei FALSE TRUE
nl no|not geen|niet FALSE TRUE
es Coagulase-negative Staphylococcus Staphylococcus coagulasa negativo FALSE FALSE
es Coagulase-positive Staphylococcus Staphylococcus coagulasa positivo FALSE FALSE
es Beta-haemolytic Streptococcus Streptococcus Beta-hemolítico FALSE FALSE
es unknown Gram-negatives Gram negativos desconocidos FALSE FALSE
es unknown Gram-positives Gram positivos desconocidos FALSE FALSE
es unknown name nombre desconocido FALSE FALSE
es unknown kingdom reino desconocido FALSE FALSE
es unknown phylum filo desconocido FALSE FALSE
es unknown class clase desconocida FALSE FALSE
es unknown order orden desconocido FALSE FALSE
es unknown family familia desconocida FALSE FALSE
es unknown genus género desconocido FALSE FALSE
es unknown species especie desconocida FALSE FALSE
es unknown subspecies subespecie desconocida FALSE FALSE
es unknown rank rango desconocido FALSE FALSE
es CoNS SCN TRUE FALSE
es CoPS SCP TRUE FALSE
es Gram-negative Gram negativo FALSE FALSE
es Gram-positive Gram positivo FALSE FALSE
es Bacteria Bacterias FALSE FALSE
es Fungi Hongos FALSE FALSE
es Protozoa Protozoarios FALSE FALSE
es biogroup biogrupo FALSE FALSE
es biotype biotipo FALSE FALSE
es vegetative vegetativo FALSE FALSE
es ([([ ]*?)group \\1grupo FALSE FALSE
es ([([ ]*?)Group \\1Grupo FALSE FALSE
es no .*growth no .*crecimientonon FALSE TRUE
es no|not no|sin FALSE TRUE
it Coagulase-negative Staphylococcus Staphylococcus negativo coagulasi FALSE FALSE
it Coagulase-positive Staphylococcus Staphylococcus positivo coagulasi FALSE FALSE
it Beta-haemolytic Streptococcus Streptococcus Beta-emolitico FALSE FALSE
it unknown Gram-negatives Gram negativi sconosciuti FALSE FALSE
it unknown Gram-positives Gram positivi sconosciuti FALSE FALSE
it unknown name nome sconosciuto FALSE FALSE
it unknown kingdom regno sconosciuto FALSE FALSE
it unknown phylum phylum sconosciuto FALSE FALSE
it unknown class classe sconosciuta FALSE FALSE
it unknown order ordine sconosciuto FALSE FALSE
it unknown family famiglia sconosciuta FALSE FALSE
it unknown genus genere sconosciuto FALSE FALSE
it unknown species specie sconosciute FALSE FALSE
it unknown subspecies sottospecie sconosciute FALSE FALSE
it unknown rank grado sconosciuto FALSE FALSE
it Gram-negative Gram negativo FALSE FALSE
it Gram-positive Gram positivo FALSE FALSE
it Bacteria Batteri FALSE FALSE
it Fungi Fungo FALSE FALSE
it Protozoa Protozoi FALSE FALSE
it biogroup biogruppo FALSE FALSE
it biotype biotipo FALSE FALSE
it vegetative vegetativo FALSE FALSE
it ([([ ]*?)group \\1gruppo FALSE FALSE
it ([([ ]*?)Group \\1Gruppo FALSE FALSE
it no .*growth sem .*crescimento FALSE TRUE
it no|not sem FALSE TRUE
fr Coagulase-negative Staphylococcus Staphylococcus à coagulase négative FALSE FALSE
fr Coagulase-positive Staphylococcus Staphylococcus à coagulase positif FALSE FALSE
fr Beta-haemolytic Streptococcus Streptococcus Bêta-hémolytique FALSE FALSE
fr unknown Gram-negatives Gram négatifs inconnus FALSE FALSE
fr unknown Gram-positives Gram positifs inconnus FALSE FALSE
fr unknown name nom inconnu FALSE FALSE
fr unknown kingdom règme inconnu FALSE FALSE
fr unknown phylum embranchement inconnu FALSE FALSE
fr unknown class classe inconnue FALSE FALSE
fr unknown order ordre inconnu FALSE FALSE
fr unknown family famille inconnue FALSE FALSE
fr unknown genus genre inconnu FALSE FALSE
fr unknown species espèce inconnue FALSE FALSE
fr unknown subspecies sous-espèce inconnue FALSE FALSE
fr unknown rank rang inconnu FALSE FALSE
fr Gram-negative Gram négatif FALSE FALSE
fr Gram-positive Gram positif FALSE FALSE
fr Bacteria Bactéries FALSE FALSE
fr Fungi Champignons FALSE FALSE
fr Protozoa Protozoaires FALSE FALSE
fr biogroup biogroupe FALSE FALSE
fr vegetative végétatif FALSE FALSE
fr ([([ ]*?)group \\1groupe FALSE FALSE
fr ([([ ]*?)Group \\1Groupe FALSE FALSE
fr no .*growth pas .*croissance FALSE TRUE
fr no|not non FALSE TRUE
pt Coagulase-negative Staphylococcus Staphylococcus coagulase negativo FALSE FALSE
pt Coagulase-positive Staphylococcus Staphylococcus coagulase positivo FALSE FALSE
pt Beta-haemolytic Streptococcus Streptococcus Beta-hemolítico FALSE FALSE
pt unknown Gram-negatives Gram negativos desconhecidos FALSE FALSE
pt unknown Gram-positives Gram positivos desconhecidos FALSE FALSE
pt unknown name nome desconhecido FALSE FALSE
pt unknown kingdom reino desconhecido FALSE FALSE
pt unknown phylum filo desconhecido FALSE FALSE
pt unknown class classe desconhecida FALSE FALSE
pt unknown order ordem desconhecido FALSE FALSE
pt unknown family família desconhecida FALSE FALSE
pt unknown genus gênero desconhecido FALSE FALSE
pt unknown species espécies desconhecida FALSE FALSE
pt unknown subspecies subespécies desconhecida FALSE FALSE
pt unknown rank classificação desconhecido FALSE FALSE
pt Gram-negative Gram negativo FALSE FALSE
pt Gram-positive Gram positivo FALSE FALSE
pt Bacteria Bactérias FALSE FALSE
pt Fungi Fungos FALSE FALSE
pt Protozoa Protozoários FALSE FALSE
pt biogroup biogrupo FALSE FALSE
pt biotype biótipo FALSE FALSE
pt vegetative vegetativo FALSE FALSE
pt ([([ ]*?)group \\1grupo FALSE FALSE
pt ([([ ]*?)Group \\1Grupo FALSE FALSE
pt no .*growth sem .*crescimento FALSE TRUE
pt no|not sem FALSE TRUE
de clavulanic acid Clavulansäure FALSE TRUE
nl 4-aminosalicylic acid 4-aminosalicylzuur
nl Adefovir dipivoxil Adefovir
nl Aldesulfone sodium Aldesulfon
nl Amikacin Amikacine
nl Amoxicillin Amoxicilline
nl Amoxicillin/beta-lactamase inhibitor Amoxicilline/enzymremmer
nl Amphotericin B Amfotericine B
nl Ampicillin Ampicilline
nl Ampicillin/beta-lactamase inhibitor Ampicilline/enzymremmer
nl Anidulafungin Anidulafungine
nl Azidocillin Azidocilline
nl Azithromycin Azitromycine
nl Azlocillin Azlocilline
nl Bacampicillin Bacampicilline
nl Bacitracin Bacitracine
nl Benzathine benzylpenicillin Benzylpenicillinebenzathine
nl Benzathine phenoxymethylpenicillin Fenoxymethylpenicillinebenzathine
nl Benzylpenicillin Benzylpenicilline
nl Calcium aminosalicylate Aminosalicylzuur
nl Capreomycin Capreomycine
nl Carbenicillin Carbenicilline
nl Carindacillin Carindacilline
nl Caspofungin Caspofungine
nl Ce(f|ph)acetrile Cefacetril FALSE
nl Ce(f|ph)alexin Cefalexine FALSE FALSE
nl Ce(f|ph)alotin Cefalotine FALSE
nl Ce(f|ph)amandole Cefamandol FALSE
nl Ce(f|ph)apirin Cefapirine FALSE
nl Ce(f|ph)azedone Cefazedon FALSE
nl Ce(f|ph)azolin Cefazoline FALSE
nl Ce(f|ph)alothin Cefalotine FALSE
nl Ce(f|ph)alexin Cefalexine FALSE
nl Ce(f|ph)epime Cefepim FALSE
nl Ce(f|ph)ixime Cefixim FALSE
nl Ce(f|ph)menoxime Cefmenoxim FALSE
nl Ce(f|ph)metazole Cefmetazol FALSE
nl Ce(f|ph)odizime Cefodizim FALSE
nl Ce(f|ph)onicid Cefonicide FALSE
nl Ce(f|ph)operazone Cefoperazon FALSE
nl Ce(f|ph)operazone/beta-lactamase inhibitor Cefoperazon/enzymremmer FALSE
nl Ce(f|ph)otaxime Cefotaxim FALSE
nl Ce(f|ph)oxitin Cefoxitine FALSE
nl Ce(f|ph)pirome Cefpirom FALSE
nl Ce(f|ph)podoxime Cefpodoxim FALSE
nl Ce(f|ph)radine Cefradine FALSE
nl Ce(f|ph)sulodin Cefsulodine FALSE
nl Ce(f|ph)tazidime Ceftazidim FALSE
nl Ce(f|ph)tezole Ceftezol FALSE
nl Ce(f|ph)tizoxime Ceftizoxim FALSE
nl Ce(f|ph)triaxone Ceftriaxon FALSE
nl Ce(f|ph)uroxime Cefuroxim FALSE
nl Ce(f|ph)uroxime/metronidazole Cefuroxim/andere antibacteriele middelen FALSE
nl Chloramphenicol Chlooramfenicol
nl Chlortetracycline Chloortetracycline
nl Cinoxacin Cinoxacine
nl Ciprofloxacin Ciprofloxacine
nl Clarithromycin Claritromycine
nl Clavulanic acid Clavulaanzuur
nl clavulanic acid clavulaanzuur
nl Clindamycin Clindamycine
nl Clometocillin Clometocilline
nl Clotrimazole Clotrimazol
nl Cloxacillin Cloxacilline
nl Colistin Colistine
nl Dapsone Dapson
nl Daptomycin Daptomycine
nl Dibekacin Dibekacine
nl Dicloxacillin Dicloxacilline
nl Dirithromycin Diritromycine
nl Econazole Econazol
nl Enoxacin Enoxacine
nl Epicillin Epicilline
nl Erythromycin Erytromycine
nl Ethambutol/isoniazid Ethambutol/isoniazide
nl Fleroxacin Fleroxacine
nl Flucloxacillin Flucloxacilline
nl Fluconazole Fluconazol
nl Flucytosine Fluorocytosine
nl Flurithromycin Fluritromycine
nl Fosfomycin Fosfomycine
nl Fusidic acid Fusidinezuur
nl Gatifloxacin Gatifloxacine
nl Gemifloxacin Gemifloxacine
nl Gentamicin Gentamicine
nl Grepafloxacin Grepafloxacine
nl Hachimycin Hachimycine
nl Hetacillin Hetacilline
nl Imipenem/cilastatin Imipenem/enzymremmer
nl Inosine pranobex Inosiplex
nl Isepamicin Isepamicine
nl Isoconazole Isoconazol
nl Isoniazid Isoniazide
nl Itraconazole Itraconazol
nl Josamycin Josamycine
nl Kanamycin Kanamycine
nl Ketoconazole Ketoconazol
nl Levofloxacin Levofloxacine
nl Lincomycin Lincomycine
nl Lomefloxacin Lomefloxacine
nl Lysozyme Lysozym
nl Mandelic acid Amandelzuur
nl Metampicillin Metampicilline
nl Meticillin Meticilline
nl Metisazone Metisazon
nl Metronidazole Metronidazol
nl Mezlocillin Mezlocilline
nl Micafungin Micafungine
nl Miconazole Miconazol
nl Midecamycin Midecamycine
nl Miocamycin Miocamycine
nl Moxifloxacin Moxifloxacine
nl Mupirocin Mupirocine
nl Nalidixic acid Nalidixinezuur
nl Neomycin Neomycine
nl Netilmicin Netilmicine
nl Nitrofurantoin Nitrofurantoine
nl Norfloxacin Norfloxacine
nl Novobiocin Novobiocine
nl Nystatin Nystatine
nl Ofloxacin Ofloxacine
nl Oleandomycin Oleandomycine
nl Ornidazole Ornidazol
nl Oxacillin Oxacilline
nl Oxolinic acid Oxolinezuur
nl Oxytetracycline Oxytetracycline
nl Pazufloxacin Pazufloxacine
nl Pefloxacin Pefloxacine
nl Penamecillin Penamecilline
nl Penicillin Penicilline
nl Pheneticillin Feneticilline
nl Phenoxymethylpenicillin Fenoxymethylpenicilline
nl Pipemidic acid Pipemidinezuur
nl Piperacillin Piperacilline
nl Piperacillin/beta-lactamase inhibitor Piperacilline/enzymremmer
nl Piromidic acid Piromidinezuur
nl Pivampicillin Pivampicilline
nl Polymyxin B Polymyxine B
nl Posaconazole Posaconazol
nl Pristinamycin Pristinamycine
nl Procaine benzylpenicillin Benzylpenicillineprocaine
nl Propicillin Propicilline
nl Prulifloxacin Prulifloxacine
nl Quinupristin/dalfopristin Quinupristine/dalfopristine
nl Ribostamycin Ribostamycine
nl Rifabutin Rifabutine
nl Rifampicin Rifampicine
nl Rifampicin/pyrazinamide/ethambutol/isoniazid Rifampicine/pyrazinamide/ethambutol/isoniazide
nl Rifampicin/pyrazinamide/isoniazid Rifampicine/pyrazinamide/isoniazide
nl Rifampicin/isoniazid Rifampicine/isoniazide
nl Rifamycin Rifamycine
nl Rifaximin Rifaximine
nl Rokitamycin Rokitamycine
nl Rosoxacin Rosoxacine
nl Roxithromycin Roxitromycine
nl Rufloxacin Rufloxacine
nl Sisomicin Sisomicine
nl Sodium aminosalicylate Aminosalicylzuur
nl Sparfloxacin Sparfloxacine
nl Spectinomycin Spectinomycine
nl Spiramycin Spiramycine
nl Spiramycin/metronidazole Spiramycine/metronidazol
nl Staphylococcus immunoglobulin Stafylokokkenimmunoglobuline
nl Streptoduocin Streptoduocine
nl Streptomycin Streptomycine
nl Streptomycin/isoniazid Streptomycine/isoniazide
nl Sulbenicillin Sulbenicilline
nl Sulfadiazine/tetroxoprim Sulfadiazine/tetroxoprim
nl Sulfadiazine/trimethoprim Sulfadiazine/trimethoprim
nl Sulfadimidine/trimethoprim Sulfadimidine/trimethoprim
nl Sulfafurazole Sulfafurazol
nl Sulfaisodimidine Sulfisomidine
nl Sulfalene Sulfaleen
nl Sulfamazone Sulfamazon
nl Sulfamerazine/trimethoprim Sulfamerazine/trimethoprim
nl Sulfamethizole Sulfamethizol
nl Sulfamethoxazole Sulfamethoxazol
nl Sulfamethoxazole/trimethoprim Sulfamethoxazol/trimethoprim
nl Sulfametoxydiazine Sulfamethoxydiazine
nl Sulfametrole/trimethoprim Sulfametrol/trimethoprim
nl Sulfamoxole Sulfamoxol
nl Sulfamoxole/trimethoprim Sulfamoxol/trimethoprim
nl Sulfaperin Sulfaperine
nl Sulfaphenazole Sulfafenazol
nl Sulfathiazole Sulfathiazol
nl Sulfathiourea Sulfathioureum
nl Sultamicillin Sultamicilline
nl Talampicillin Talampicilline
nl Teicoplanin Teicoplanine
nl Telithromycin Telitromycine
nl Temafloxacin Temafloxacine
nl Temocillin Temocilline
nl Tenofovir disoproxil Tenofovir
nl Terizidone Terizidon
nl Thiamphenicol Thiamfenicol
nl Thioacetazone/isoniazid Thioacetazon/isoniazide
nl Ticarcillin Ticarcilline
nl Ticarcillin/beta-lactamase inhibitor Ticarcilline/enzymremmer
nl Ticarcillin/clavulanic acid Ticarcilline/clavulaanzuur
nl Tinidazole Tinidazol
nl Tobramycin Tobramycine
nl Trimethoprim/sulfamethoxazole Cotrimoxazol
nl Troleandomycin Troleandomycine
nl Trovafloxacin Trovafloxacine
nl Vancomycin Vancomycine
nl Voriconazole Voriconazol
nl Aminoglycosides Aminoglycosiden TRUE FALSE
nl Amphenicols Amfenicolen TRUE FALSE
nl Antifungals/antimycotics Antifungica/antimycotica TRUE FALSE
nl Antimycobacterials Antimycobacteriele middelen TRUE FALSE
nl Beta-lactams/penicillins Beta-lactams/penicillines TRUE FALSE
nl Cephalosporins (1st gen.) Cefalosporines (1e gen.) TRUE FALSE
nl Cephalosporins (2nd gen.) Cefalosporines (2e gen.) TRUE FALSE
nl Cephalosporins (3rd gen.) Cefalosporines (3e gen.) TRUE FALSE
nl Cephalosporins (4th gen.) Cefalosporines (4e gen.) TRUE FALSE
nl Cephalosporins (5th gen.) Cefalosporines (5e gen.) TRUE FALSE
nl Cephalosporins (unclassified gen.) Cefalosporines (ongeclassificeerd) TRUE FALSE
nl Cephalosporins Cefalosporines TRUE FALSE
nl Glycopeptides Glycopeptiden TRUE FALSE
nl Macrolides/lincosamides Macroliden/lincosamiden TRUE FALSE
nl Other antibacterials Overige antibiotica TRUE FALSE
nl Polymyxins Polymyxines TRUE FALSE
nl Quinolones Quinolonen TRUE FALSE
lang pattern replacement fixed ignore.case affect_mo_name
de Coagulase-negative Staphylococcus Koagulase-negative Staphylococcus FALSE FALSE TRUE
de Coagulase-positive Staphylococcus Koagulase-positive Staphylococcus FALSE FALSE TRUE
de Beta-haemolytic Streptococcus Beta-hämolytischer Streptococcus FALSE FALSE TRUE
de unknown Gram-negatives unbekannte Gramnegativen FALSE FALSE TRUE
de unknown Gram-positives unbekannte Grampositiven FALSE FALSE TRUE
de unknown fungus unbekannter Pilze FALSE FALSE TRUE
de unknown yeast unbekannte Hefe FALSE FALSE TRUE
de unknown name unbekannte Name FALSE FALSE TRUE
de unknown kingdom unbekanntes Reich FALSE FALSE TRUE
de unknown phylum unbekannter Stamm FALSE FALSE TRUE
de unknown class unbekannte Klasse FALSE FALSE TRUE
de unknown order unbekannte Ordnung FALSE FALSE TRUE
de unknown family unbekannte Familie FALSE FALSE TRUE
de unknown genus unbekannte Gattung FALSE FALSE TRUE
de unknown species unbekannte Art FALSE FALSE TRUE
de unknown subspecies unbekannte Unterart FALSE FALSE TRUE
de unknown rank unbekannter Rang FALSE FALSE TRUE
de CoNS KNS TRUE FALSE TRUE
de CoPS KPS TRUE FALSE TRUE
de Gram-negative Gramnegativ FALSE FALSE FALSE
de Gram-positive Grampositiv FALSE FALSE FALSE
de ^Bacteria$ Bakterien FALSE FALSE FALSE
de ^Fungi$ Pilze FALSE FALSE FALSE
de ^Yeasts$ Hefen FALSE FALSE FALSE
de ^Protozoa$ Protozoen FALSE FALSE FALSE
de biogroup Biogruppe FALSE FALSE FALSE
de biotype Biotyp FALSE FALSE FALSE
de vegetative vegetativ FALSE FALSE FALSE
de ([([ ]*?)group \\1Gruppe FALSE FALSE FALSE
de ([([ ]*?)Group \\1Gruppe FALSE FALSE FALSE
de no .*growth keine? .*wachstum FALSE TRUE FALSE
de (^| )no|not keine? FALSE TRUE FALSE
nl Coagulase-negative Staphylococcus Coagulase-negatieve Staphylococcus FALSE FALSE TRUE
nl Coagulase-positive Staphylococcus Coagulase-positieve Staphylococcus FALSE FALSE TRUE
nl Beta-haemolytic Streptococcus Beta-hemolytische Streptococcus FALSE FALSE TRUE
nl unknown Gram-negatives onbekende Gram-negatieven FALSE FALSE TRUE
nl unknown Gram-positives onbekende Gram-positieven FALSE FALSE TRUE
nl unknown fungus onbekende schimmel FALSE FALSE TRUE
nl unknown yeast onbekende gist FALSE FALSE TRUE
nl unknown name onbekende naam FALSE FALSE TRUE
nl unknown kingdom onbekend koninkrijk FALSE FALSE TRUE
nl unknown phylum onbekend fylum FALSE FALSE TRUE
nl unknown class onbekende klasse FALSE FALSE TRUE
nl unknown order onbekende orde FALSE FALSE TRUE
nl unknown family onbekende familie FALSE FALSE TRUE
nl unknown genus onbekend geslacht FALSE FALSE TRUE
nl unknown species onbekende soort FALSE FALSE TRUE
nl unknown subspecies onbekende ondersoort FALSE FALSE TRUE
nl unknown rank onbekende rang FALSE FALSE TRUE
nl CoNS CNS TRUE FALSE TRUE
nl CoPS CPS TRUE FALSE TRUE
nl Gram-negative Gram-negatief FALSE FALSE FALSE
nl Gram-positive Gram-positief FALSE FALSE FALSE
nl ^Bacteria$ Bacteriën FALSE FALSE FALSE
nl ^Fungi$ Schimmels FALSE FALSE FALSE
nl ^Yeasts$ Gisten FALSE FALSE FALSE
nl ^Protozoa$ Protozoën FALSE FALSE FALSE
nl biogroup biogroep FALSE FALSE FALSE
nl vegetative vegetatief FALSE FALSE FALSE
nl ([([ ]*?)group \\1groep FALSE FALSE FALSE
nl ([([ ]*?)Group \\1Groep FALSE FALSE FALSE
nl antibiotic antibioticum FALSE FALSE FALSE
nl Antibiotic Antibioticum FALSE FALSE FALSE
nl Drug Middel FALSE FALSE FALSE
nl drug middel FALSE FALSE FALSE
nl no .*growth geen .*groei FALSE TRUE FALSE
nl no|not geen|niet FALSE TRUE FALSE
es Coagulase-negative Staphylococcus Staphylococcus coagulasa negativo FALSE FALSE TRUE
es Coagulase-positive Staphylococcus Staphylococcus coagulasa positivo FALSE FALSE TRUE
es Beta-haemolytic Streptococcus Streptococcus Beta-hemolítico FALSE FALSE TRUE
es unknown Gram-negatives Gram negativos desconocidos FALSE FALSE TRUE
es unknown Gram-positives Gram positivos desconocidos FALSE FALSE TRUE
es unknown fungus hongo desconocido FALSE FALSE TRUE
es unknown yeast levadura desconocida FALSE FALSE TRUE
es unknown name nombre desconocido FALSE FALSE TRUE
es unknown kingdom reino desconocido FALSE FALSE TRUE
es unknown phylum filo desconocido FALSE FALSE TRUE
es unknown class clase desconocida FALSE FALSE TRUE
es unknown order orden desconocido FALSE FALSE TRUE
es unknown family familia desconocida FALSE FALSE TRUE
es unknown genus género desconocido FALSE FALSE TRUE
es unknown species especie desconocida FALSE FALSE TRUE
es unknown subspecies subespecie desconocida FALSE FALSE TRUE
es unknown rank rango desconocido FALSE FALSE TRUE
es CoNS SCN TRUE FALSE TRUE
es CoPS SCP TRUE FALSE TRUE
es Gram-negative Gram negativo FALSE FALSE FALSE
es Gram-positive Gram positivo FALSE FALSE FALSE
es ^Bacteria$ Bacterias FALSE FALSE FALSE
es ^Fungi$ Hongos FALSE FALSE FALSE
es ^Yeasts$ Levaduras FALSE FALSE FALSE
es ^Protozoa$ Protozoarios FALSE FALSE FALSE
es biogroup biogrupo FALSE FALSE FALSE
es biotype biotipo FALSE FALSE FALSE
es vegetative vegetativo FALSE FALSE FALSE
es ([([ ]*?)group \\1grupo FALSE FALSE FALSE
es ([([ ]*?)Group \\1Grupo FALSE FALSE FALSE
es no .*growth no .*crecimientonon FALSE TRUE FALSE
es no|not no|sin FALSE TRUE FALSE
it Coagulase-negative Staphylococcus Staphylococcus negativo coagulasi FALSE FALSE TRUE
it Coagulase-positive Staphylococcus Staphylococcus positivo coagulasi FALSE FALSE TRUE
it Beta-haemolytic Streptococcus Streptococcus Beta-emolitico FALSE FALSE TRUE
it unknown Gram-negatives Gram negativi sconosciuti FALSE FALSE TRUE
it unknown Gram-positives Gram positivi sconosciuti FALSE FALSE TRUE
it unknown fungus fungo sconosciuto FALSE FALSE TRUE
it unknown yeast lievito sconosciuto FALSE FALSE TRUE
it unknown name nome sconosciuto FALSE FALSE TRUE
it unknown kingdom regno sconosciuto FALSE FALSE TRUE
it unknown phylum phylum sconosciuto FALSE FALSE TRUE
it unknown class classe sconosciuta FALSE FALSE TRUE
it unknown order ordine sconosciuto FALSE FALSE TRUE
it unknown family famiglia sconosciuta FALSE FALSE TRUE
it unknown genus genere sconosciuto FALSE FALSE TRUE
it unknown species specie sconosciute FALSE FALSE TRUE
it unknown subspecies sottospecie sconosciute FALSE FALSE TRUE
it unknown rank grado sconosciuto FALSE FALSE TRUE
it Gram-negative Gram negativo FALSE FALSE FALSE
it Gram-positive Gram positivo FALSE FALSE FALSE
it ^Bacteria$ Batteri FALSE FALSE FALSE
it ^Fungi$ Funghi FALSE FALSE FALSE
it ^Yeasts$ Lieviti FALSE FALSE FALSE
it ^Protozoa$ Protozoi FALSE FALSE FALSE
it biogroup biogruppo FALSE FALSE FALSE
it biotype biotipo FALSE FALSE FALSE
it vegetative vegetativo FALSE FALSE FALSE
it ([([ ]*?)group \\1gruppo FALSE FALSE FALSE
it ([([ ]*?)Group \\1Gruppo FALSE FALSE FALSE
it no .*growth sem .*crescimento FALSE TRUE FALSE
it no|not sem FALSE TRUE FALSE
fr Coagulase-negative Staphylococcus Staphylococcus à coagulase négative FALSE FALSE TRUE
fr Coagulase-positive Staphylococcus Staphylococcus à coagulase positif FALSE FALSE TRUE
fr Beta-haemolytic Streptococcus Streptococcus Bêta-hémolytique FALSE FALSE TRUE
fr unknown Gram-negatives Gram négatifs inconnus FALSE FALSE TRUE
fr unknown Gram-positives Gram positifs inconnus FALSE FALSE TRUE
fr unknown fungus champignon inconnu FALSE FALSE TRUE
fr unknown yeast levure inconnue FALSE FALSE TRUE
fr unknown name nom inconnu FALSE FALSE TRUE
fr unknown kingdom règme inconnu FALSE FALSE TRUE
fr unknown phylum embranchement inconnu FALSE FALSE TRUE
fr unknown class classe inconnue FALSE FALSE TRUE
fr unknown order ordre inconnu FALSE FALSE TRUE
fr unknown family famille inconnue FALSE FALSE TRUE
fr unknown genus genre inconnu FALSE FALSE TRUE
fr unknown species espèce inconnue FALSE FALSE TRUE
fr unknown subspecies sous-espèce inconnue FALSE FALSE TRUE
fr unknown rank rang inconnu FALSE FALSE TRUE
fr Gram-negative Gram négatif FALSE FALSE FALSE
fr Gram-positive Gram positif FALSE FALSE FALSE
fr ^Bacteria$ Bactéries FALSE FALSE FALSE
fr ^Fungi$ Champignons FALSE FALSE FALSE
fr ^Yeasts$ Levures FALSE FALSE FALSE
fr ^Protozoa$ Protozoaires FALSE FALSE FALSE
fr biogroup biogroupe FALSE FALSE FALSE
fr vegetative végétatif FALSE FALSE FALSE
fr ([([ ]*?)group \\1groupe FALSE FALSE FALSE
fr ([([ ]*?)Group \\1Groupe FALSE FALSE FALSE
fr no .*growth pas .*croissance FALSE TRUE FALSE
fr no|not non FALSE TRUE FALSE
pt Coagulase-negative Staphylococcus Staphylococcus coagulase negativo FALSE FALSE TRUE
pt Coagulase-positive Staphylococcus Staphylococcus coagulase positivo FALSE FALSE TRUE
pt Beta-haemolytic Streptococcus Streptococcus Beta-hemolítico FALSE FALSE TRUE
pt unknown Gram-negatives Gram negativos desconhecidos FALSE FALSE TRUE
pt unknown Gram-positives Gram positivos desconhecidos FALSE FALSE TRUE
pt unknown fungus fungo desconhecido FALSE FALSE TRUE
pt unknown yeast levedura desconhecida FALSE FALSE TRUE
pt unknown name nome desconhecido FALSE FALSE TRUE
pt unknown kingdom reino desconhecido FALSE FALSE TRUE
pt unknown phylum filo desconhecido FALSE FALSE TRUE
pt unknown class classe desconhecida FALSE FALSE TRUE
pt unknown order ordem desconhecido FALSE FALSE TRUE
pt unknown family família desconhecida FALSE FALSE TRUE
pt unknown genus gênero desconhecido FALSE FALSE TRUE
pt unknown species espécies desconhecida FALSE FALSE TRUE
pt unknown subspecies subespécies desconhecida FALSE FALSE TRUE
pt unknown rank classificação desconhecido FALSE FALSE TRUE
pt Gram-negative Gram negativo FALSE FALSE FALSE
pt Gram-positive Gram positivo FALSE FALSE FALSE
pt ^Bacteria$ Bactérias FALSE FALSE FALSE
pt ^Fungi$ Fungos FALSE FALSE FALSE
pt ^Yeasts$ Leveduras FALSE FALSE FALSE
pt ^Protozoa$ Protozoários FALSE FALSE FALSE
pt biogroup biogrupo FALSE FALSE FALSE
pt biotype biótipo FALSE FALSE FALSE
pt vegetative vegetativo FALSE FALSE FALSE
pt ([([ ]*?)group \\1grupo FALSE FALSE FALSE
pt ([([ ]*?)Group \\1Grupo FALSE FALSE FALSE
pt no .*growth sem .*crescimento FALSE TRUE FALSE
pt no|not sem FALSE TRUE FALSE
de clavulanic acid Clavulansäure FALSE TRUE FALSE
nl 4-aminosalicylic acid 4-aminosalicylzuur TRUE FALSE FALSE
nl Adefovir dipivoxil Adefovir TRUE FALSE FALSE
nl Aldesulfone sodium Aldesulfon TRUE FALSE FALSE
nl Amikacin Amikacine TRUE FALSE FALSE
nl Amoxicillin Amoxicilline TRUE FALSE FALSE
nl Amoxicillin/beta-lactamase inhibitor Amoxicilline/enzymremmer TRUE FALSE FALSE
nl Amphotericin B Amfotericine B TRUE FALSE FALSE
nl Ampicillin Ampicilline TRUE FALSE FALSE
nl Ampicillin/beta-lactamase inhibitor Ampicilline/enzymremmer TRUE FALSE FALSE
nl Anidulafungin Anidulafungine TRUE FALSE FALSE
nl Azidocillin Azidocilline TRUE FALSE FALSE
nl Azithromycin Azitromycine TRUE FALSE FALSE
nl Azlocillin Azlocilline TRUE FALSE FALSE
nl Bacampicillin Bacampicilline TRUE FALSE FALSE
nl Bacitracin Bacitracine TRUE FALSE FALSE
nl Benzathine benzylpenicillin Benzylpenicillinebenzathine TRUE FALSE FALSE
nl Benzathine phenoxymethylpenicillin Fenoxymethylpenicillinebenzathine TRUE FALSE FALSE
nl Benzylpenicillin Benzylpenicilline TRUE FALSE FALSE
nl Calcium aminosalicylate Aminosalicylzuur TRUE FALSE FALSE
nl Capreomycin Capreomycine TRUE FALSE FALSE
nl Carbenicillin Carbenicilline TRUE FALSE FALSE
nl Carindacillin Carindacilline TRUE FALSE FALSE
nl Caspofungin Caspofungine TRUE FALSE FALSE
nl Ce(f|ph)acetrile Cefacetril FALSE FALSE FALSE
nl Ce(f|ph)alexin Cefalexine FALSE FALSE FALSE
nl Ce(f|ph)alotin Cefalotine FALSE FALSE FALSE
nl Ce(f|ph)amandole Cefamandol FALSE FALSE FALSE
nl Ce(f|ph)apirin Cefapirine FALSE FALSE FALSE
nl Ce(f|ph)azedone Cefazedon FALSE FALSE FALSE
nl Ce(f|ph)azolin Cefazoline FALSE FALSE FALSE
nl Ce(f|ph)alothin Cefalotine FALSE FALSE FALSE
nl Ce(f|ph)alexin Cefalexine FALSE FALSE FALSE
nl Ce(f|ph)epime Cefepim FALSE FALSE FALSE
nl Ce(f|ph)ixime Cefixim FALSE FALSE FALSE
nl Ce(f|ph)menoxime Cefmenoxim FALSE FALSE FALSE
nl Ce(f|ph)metazole Cefmetazol FALSE FALSE FALSE
nl Ce(f|ph)odizime Cefodizim FALSE FALSE FALSE
nl Ce(f|ph)onicid Cefonicide FALSE FALSE FALSE
nl Ce(f|ph)operazone Cefoperazon FALSE FALSE FALSE
nl Ce(f|ph)operazone/beta-lactamase inhibitor Cefoperazon/enzymremmer FALSE FALSE FALSE
nl Ce(f|ph)otaxime Cefotaxim FALSE FALSE FALSE
nl Ce(f|ph)oxitin Cefoxitine FALSE FALSE FALSE
nl Ce(f|ph)pirome Cefpirom FALSE FALSE FALSE
nl Ce(f|ph)podoxime Cefpodoxim FALSE FALSE FALSE
nl Ce(f|ph)radine Cefradine FALSE FALSE FALSE
nl Ce(f|ph)sulodin Cefsulodine FALSE FALSE FALSE
nl Ce(f|ph)tazidime Ceftazidim FALSE FALSE FALSE
nl Ce(f|ph)tezole Ceftezol FALSE FALSE FALSE
nl Ce(f|ph)tizoxime Ceftizoxim FALSE FALSE FALSE
nl Ce(f|ph)triaxone Ceftriaxon FALSE FALSE FALSE
nl Ce(f|ph)uroxime Cefuroxim FALSE FALSE FALSE
nl Ce(f|ph)uroxime/metronidazole Cefuroxim/andere antibacteriele middelen FALSE FALSE FALSE
nl Chloramphenicol Chlooramfenicol TRUE FALSE FALSE
nl Chlortetracycline Chloortetracycline TRUE FALSE FALSE
nl Cinoxacin Cinoxacine TRUE FALSE FALSE
nl Ciprofloxacin Ciprofloxacine TRUE FALSE FALSE
nl Clarithromycin Claritromycine TRUE FALSE FALSE
nl Clavulanic acid Clavulaanzuur TRUE FALSE FALSE
nl clavulanic acid clavulaanzuur TRUE FALSE FALSE
nl Clindamycin Clindamycine TRUE FALSE FALSE
nl Clometocillin Clometocilline TRUE FALSE FALSE
nl Clotrimazole Clotrimazol TRUE FALSE FALSE
nl Cloxacillin Cloxacilline TRUE FALSE FALSE
nl Colistin Colistine TRUE FALSE FALSE
nl Dapsone Dapson TRUE FALSE FALSE
nl Daptomycin Daptomycine TRUE FALSE FALSE
nl Dibekacin Dibekacine TRUE FALSE FALSE
nl Dicloxacillin Dicloxacilline TRUE FALSE FALSE
nl Dirithromycin Diritromycine TRUE FALSE FALSE
nl Econazole Econazol TRUE FALSE FALSE
nl Enoxacin Enoxacine TRUE FALSE FALSE
nl Epicillin Epicilline TRUE FALSE FALSE
nl Erythromycin Erytromycine TRUE FALSE FALSE
nl Ethambutol/isoniazid Ethambutol/isoniazide TRUE FALSE FALSE
nl Fleroxacin Fleroxacine TRUE FALSE FALSE
nl Flucloxacillin Flucloxacilline TRUE FALSE FALSE
nl Fluconazole Fluconazol TRUE FALSE FALSE
nl Flucytosine Fluorocytosine TRUE FALSE FALSE
nl Flurithromycin Fluritromycine TRUE FALSE FALSE
nl Fosfomycin Fosfomycine TRUE FALSE FALSE
nl Fusidic acid Fusidinezuur TRUE FALSE FALSE
nl Gatifloxacin Gatifloxacine TRUE FALSE FALSE
nl Gemifloxacin Gemifloxacine TRUE FALSE FALSE
nl Gentamicin Gentamicine TRUE FALSE FALSE
nl Grepafloxacin Grepafloxacine TRUE FALSE FALSE
nl Hachimycin Hachimycine TRUE FALSE FALSE
nl Hetacillin Hetacilline TRUE FALSE FALSE
nl Imipenem/cilastatin Imipenem/enzymremmer TRUE FALSE FALSE
nl Inosine pranobex Inosiplex TRUE FALSE FALSE
nl Isepamicin Isepamicine TRUE FALSE FALSE
nl Isoconazole Isoconazol TRUE FALSE FALSE
nl Isoniazid Isoniazide TRUE FALSE FALSE
nl Itraconazole Itraconazol TRUE FALSE FALSE
nl Josamycin Josamycine TRUE FALSE FALSE
nl Kanamycin Kanamycine TRUE FALSE FALSE
nl Ketoconazole Ketoconazol TRUE FALSE FALSE
nl Levofloxacin Levofloxacine TRUE FALSE FALSE
nl Lincomycin Lincomycine TRUE FALSE FALSE
nl Lomefloxacin Lomefloxacine TRUE FALSE FALSE
nl Lysozyme Lysozym TRUE FALSE FALSE
nl Mandelic acid Amandelzuur TRUE FALSE FALSE
nl Metampicillin Metampicilline TRUE FALSE FALSE
nl Meticillin Meticilline TRUE FALSE FALSE
nl Metisazone Metisazon TRUE FALSE FALSE
nl Metronidazole Metronidazol TRUE FALSE FALSE
nl Mezlocillin Mezlocilline TRUE FALSE FALSE
nl Micafungin Micafungine TRUE FALSE FALSE
nl Miconazole Miconazol TRUE FALSE FALSE
nl Midecamycin Midecamycine TRUE FALSE FALSE
nl Miocamycin Miocamycine TRUE FALSE FALSE
nl Moxifloxacin Moxifloxacine TRUE FALSE FALSE
nl Mupirocin Mupirocine TRUE FALSE FALSE
nl Nalidixic acid Nalidixinezuur TRUE FALSE FALSE
nl Neomycin Neomycine TRUE FALSE FALSE
nl Netilmicin Netilmicine TRUE FALSE FALSE
nl Nitrofurantoin Nitrofurantoine TRUE FALSE FALSE
nl Norfloxacin Norfloxacine TRUE FALSE FALSE
nl Novobiocin Novobiocine TRUE FALSE FALSE
nl Nystatin Nystatine TRUE FALSE FALSE
nl Ofloxacin Ofloxacine TRUE FALSE FALSE
nl Oleandomycin Oleandomycine TRUE FALSE FALSE
nl Ornidazole Ornidazol TRUE FALSE FALSE
nl Oxacillin Oxacilline TRUE FALSE FALSE
nl Oxolinic acid Oxolinezuur TRUE FALSE FALSE
nl Oxytetracycline Oxytetracycline TRUE FALSE FALSE
nl Pazufloxacin Pazufloxacine TRUE FALSE FALSE
nl Pefloxacin Pefloxacine TRUE FALSE FALSE
nl Penamecillin Penamecilline TRUE FALSE FALSE
nl Penicillin Penicilline TRUE FALSE FALSE
nl Pheneticillin Feneticilline TRUE FALSE FALSE
nl Phenoxymethylpenicillin Fenoxymethylpenicilline TRUE FALSE FALSE
nl Pipemidic acid Pipemidinezuur TRUE FALSE FALSE
nl Piperacillin Piperacilline TRUE FALSE FALSE
nl Piperacillin/beta-lactamase inhibitor Piperacilline/enzymremmer TRUE FALSE FALSE
nl Piromidic acid Piromidinezuur TRUE FALSE FALSE
nl Pivampicillin Pivampicilline TRUE FALSE FALSE
nl Polymyxin B Polymyxine B TRUE FALSE FALSE
nl Posaconazole Posaconazol TRUE FALSE FALSE
nl Pristinamycin Pristinamycine TRUE FALSE FALSE
nl Procaine benzylpenicillin Benzylpenicillineprocaine TRUE FALSE FALSE
nl Propicillin Propicilline TRUE FALSE FALSE
nl Prulifloxacin Prulifloxacine TRUE FALSE FALSE
nl Quinupristin/dalfopristin Quinupristine/dalfopristine TRUE FALSE FALSE
nl Ribostamycin Ribostamycine TRUE FALSE FALSE
nl Rifabutin Rifabutine TRUE FALSE FALSE
nl Rifampicin Rifampicine TRUE FALSE FALSE
nl Rifampicin/pyrazinamide/ethambutol/isoniazid Rifampicine/pyrazinamide/ethambutol/isoniazide TRUE FALSE FALSE
nl Rifampicin/pyrazinamide/isoniazid Rifampicine/pyrazinamide/isoniazide TRUE FALSE FALSE
nl Rifampicin/isoniazid Rifampicine/isoniazide TRUE FALSE FALSE
nl Rifamycin Rifamycine TRUE FALSE FALSE
nl Rifaximin Rifaximine TRUE FALSE FALSE
nl Rokitamycin Rokitamycine TRUE FALSE FALSE
nl Rosoxacin Rosoxacine TRUE FALSE FALSE
nl Roxithromycin Roxitromycine TRUE FALSE FALSE
nl Rufloxacin Rufloxacine TRUE FALSE FALSE
nl Sisomicin Sisomicine TRUE FALSE FALSE
nl Sodium aminosalicylate Aminosalicylzuur TRUE FALSE FALSE
nl Sparfloxacin Sparfloxacine TRUE FALSE FALSE
nl Spectinomycin Spectinomycine TRUE FALSE FALSE
nl Spiramycin Spiramycine TRUE FALSE FALSE
nl Spiramycin/metronidazole Spiramycine/metronidazol TRUE FALSE FALSE
nl Staphylococcus immunoglobulin Stafylokokkenimmunoglobuline TRUE FALSE FALSE
nl Streptoduocin Streptoduocine TRUE FALSE FALSE
nl Streptomycin Streptomycine TRUE FALSE FALSE
nl Streptomycin/isoniazid Streptomycine/isoniazide TRUE FALSE FALSE
nl Sulbenicillin Sulbenicilline TRUE FALSE FALSE
nl Sulfadiazine/tetroxoprim Sulfadiazine/tetroxoprim TRUE FALSE FALSE
nl Sulfadiazine/trimethoprim Sulfadiazine/trimethoprim TRUE FALSE FALSE
nl Sulfadimidine/trimethoprim Sulfadimidine/trimethoprim TRUE FALSE FALSE
nl Sulfafurazole Sulfafurazol TRUE FALSE FALSE
nl Sulfaisodimidine Sulfisomidine TRUE FALSE FALSE
nl Sulfalene Sulfaleen TRUE FALSE FALSE
nl Sulfamazone Sulfamazon TRUE FALSE FALSE
nl Sulfamerazine/trimethoprim Sulfamerazine/trimethoprim TRUE FALSE FALSE
nl Sulfamethizole Sulfamethizol TRUE FALSE FALSE
nl Sulfamethoxazole Sulfamethoxazol TRUE FALSE FALSE
nl Sulfamethoxazole/trimethoprim Sulfamethoxazol/trimethoprim TRUE FALSE FALSE
nl Sulfametoxydiazine Sulfamethoxydiazine TRUE FALSE FALSE
nl Sulfametrole/trimethoprim Sulfametrol/trimethoprim TRUE FALSE FALSE
nl Sulfamoxole Sulfamoxol TRUE FALSE FALSE
nl Sulfamoxole/trimethoprim Sulfamoxol/trimethoprim TRUE FALSE FALSE
nl Sulfaperin Sulfaperine TRUE FALSE FALSE
nl Sulfaphenazole Sulfafenazol TRUE FALSE FALSE
nl Sulfathiazole Sulfathiazol TRUE FALSE FALSE
nl Sulfathiourea Sulfathioureum TRUE FALSE FALSE
nl Sultamicillin Sultamicilline TRUE FALSE FALSE
nl Talampicillin Talampicilline TRUE FALSE FALSE
nl Teicoplanin Teicoplanine TRUE FALSE FALSE
nl Telithromycin Telitromycine TRUE FALSE FALSE
nl Temafloxacin Temafloxacine TRUE FALSE FALSE
nl Temocillin Temocilline TRUE FALSE FALSE
nl Tenofovir disoproxil Tenofovir TRUE FALSE FALSE
nl Terizidone Terizidon TRUE FALSE FALSE
nl Thiamphenicol Thiamfenicol TRUE FALSE FALSE
nl Thioacetazone/isoniazid Thioacetazon/isoniazide TRUE FALSE FALSE
nl Ticarcillin Ticarcilline TRUE FALSE FALSE
nl Ticarcillin/beta-lactamase inhibitor Ticarcilline/enzymremmer TRUE FALSE FALSE
nl Ticarcillin/clavulanic acid Ticarcilline/clavulaanzuur TRUE FALSE FALSE
nl Tinidazole Tinidazol TRUE FALSE FALSE
nl Tobramycin Tobramycine TRUE FALSE FALSE
nl Trimethoprim/sulfamethoxazole Cotrimoxazol TRUE FALSE FALSE
nl Troleandomycin Troleandomycine TRUE FALSE FALSE
nl Trovafloxacin Trovafloxacine TRUE FALSE FALSE
nl Vancomycin Vancomycine TRUE FALSE FALSE
nl Voriconazole Voriconazol TRUE FALSE FALSE
nl Aminoglycosides Aminoglycosiden TRUE FALSE FALSE
nl Amphenicols Amfenicolen TRUE FALSE FALSE
nl Antifungals/antimycotics Antifungica/antimycotica TRUE FALSE FALSE
nl Antimycobacterials Antimycobacteriele middelen TRUE FALSE FALSE
nl Beta-lactams/penicillins Beta-lactams/penicillines TRUE FALSE FALSE
nl Cephalosporins (1st gen.) Cefalosporines (1e gen.) TRUE FALSE FALSE
nl Cephalosporins (2nd gen.) Cefalosporines (2e gen.) TRUE FALSE FALSE
nl Cephalosporins (3rd gen.) Cefalosporines (3e gen.) TRUE FALSE FALSE
nl Cephalosporins (4th gen.) Cefalosporines (4e gen.) TRUE FALSE FALSE
nl Cephalosporins (5th gen.) Cefalosporines (5e gen.) TRUE FALSE FALSE
nl Cephalosporins (unclassified gen.) Cefalosporines (ongeclassificeerd) TRUE FALSE FALSE
nl Cephalosporins Cefalosporines TRUE FALSE FALSE
nl Glycopeptides Glycopeptiden TRUE FALSE FALSE
nl Macrolides/lincosamides Macroliden/lincosamiden TRUE FALSE FALSE
nl Other antibacterials Overige antibiotica TRUE FALSE FALSE
nl Polymyxins Polymyxines TRUE FALSE FALSE
nl Quinolones Quinolonen TRUE FALSE FALSE
1 lang pattern replacement fixed ignore.case affect_mo_name
2 de Coagulase-negative Staphylococcus Koagulase-negative Staphylococcus FALSE FALSE TRUE
3 de Coagulase-positive Staphylococcus Koagulase-positive Staphylococcus FALSE FALSE TRUE
4 de Beta-haemolytic Streptococcus Beta-hämolytischer Streptococcus FALSE FALSE TRUE
5 de unknown Gram-negatives unbekannte Gramnegativen FALSE FALSE TRUE
6 de unknown Gram-positives unbekannte Grampositiven FALSE FALSE TRUE
7 de unknown name unknown fungus unbekannte Name unbekannter Pilze FALSE FALSE TRUE
8 de unknown kingdom unknown yeast unbekanntes Reich unbekannte Hefe FALSE FALSE TRUE
9 de unknown phylum unknown name unbekannter Stamm unbekannte Name FALSE FALSE TRUE
10 de unknown class unknown kingdom unbekannte Klasse unbekanntes Reich FALSE FALSE TRUE
11 de unknown order unknown phylum unbekannte Ordnung unbekannter Stamm FALSE FALSE TRUE
12 de unknown family unknown class unbekannte Familie unbekannte Klasse FALSE FALSE TRUE
13 de unknown genus unknown order unbekannte Gattung unbekannte Ordnung FALSE FALSE TRUE
14 de unknown species unknown family unbekannte Art unbekannte Familie FALSE FALSE TRUE
15 de unknown subspecies unknown genus unbekannte Unterart unbekannte Gattung FALSE FALSE TRUE
16 de unknown rank unknown species unbekannter Rang unbekannte Art FALSE FALSE TRUE
17 de CoNS unknown subspecies KNS unbekannte Unterart TRUE FALSE FALSE TRUE
18 de CoPS unknown rank KPS unbekannter Rang TRUE FALSE FALSE TRUE
19 de Gram-negative CoNS Gramnegativ KNS FALSE TRUE FALSE TRUE
20 de Gram-positive CoPS Grampositiv KPS FALSE TRUE FALSE TRUE
21 de Bacteria Gram-negative Bakterien Gramnegativ FALSE FALSE FALSE
22 de Fungi Gram-positive Hefen/Pilze Grampositiv FALSE FALSE FALSE
23 de Protozoa ^Bacteria$ Protozoen Bakterien FALSE FALSE FALSE
24 de biogroup ^Fungi$ Biogruppe Pilze FALSE FALSE FALSE
25 de biotype ^Yeasts$ Biotyp Hefen FALSE FALSE FALSE
26 de vegetative ^Protozoa$ vegetativ Protozoen FALSE FALSE FALSE
27 de ([([ ]*?)group biogroup \\1Gruppe Biogruppe FALSE FALSE FALSE
28 de ([([ ]*?)Group biotype \\1Gruppe Biotyp FALSE FALSE FALSE
29 de no .*growth vegetative keine? .*wachstum vegetativ FALSE TRUE FALSE FALSE
30 de no|not ([([ ]*?)group keine? \\1Gruppe FALSE TRUE FALSE FALSE
31 nl de Coagulase-negative Staphylococcus ([([ ]*?)Group Coagulase-negatieve Staphylococcus \\1Gruppe FALSE FALSE FALSE
32 nl de Coagulase-positive Staphylococcus no .*growth Coagulase-positieve Staphylococcus keine? .*wachstum FALSE FALSE TRUE FALSE
33 nl de Beta-haemolytic Streptococcus (^| )no|not Beta-hemolytische Streptococcus keine? FALSE FALSE TRUE FALSE
34 nl unknown Gram-negatives Coagulase-negative Staphylococcus onbekende Gram-negatieven Coagulase-negatieve Staphylococcus FALSE FALSE TRUE
35 nl unknown Gram-positives Coagulase-positive Staphylococcus onbekende Gram-positieven Coagulase-positieve Staphylococcus FALSE FALSE TRUE
36 nl unknown name Beta-haemolytic Streptococcus onbekende naam Beta-hemolytische Streptococcus FALSE FALSE TRUE
37 nl unknown kingdom unknown Gram-negatives onbekend koninkrijk onbekende Gram-negatieven FALSE FALSE TRUE
38 nl unknown phylum unknown Gram-positives onbekend fylum onbekende Gram-positieven FALSE FALSE TRUE
39 nl unknown class unknown fungus onbekende klasse onbekende schimmel FALSE FALSE TRUE
40 nl unknown order unknown yeast onbekende orde onbekende gist FALSE FALSE TRUE
41 nl unknown family unknown name onbekende familie onbekende naam FALSE FALSE TRUE
42 nl unknown genus unknown kingdom onbekend geslacht onbekend koninkrijk FALSE FALSE TRUE
43 nl unknown species unknown phylum onbekende soort onbekend fylum FALSE FALSE TRUE
44 nl unknown subspecies unknown class onbekende ondersoort onbekende klasse FALSE FALSE TRUE
45 nl unknown rank unknown order onbekende rang onbekende orde FALSE FALSE TRUE
46 nl CoNS unknown family CNS onbekende familie TRUE FALSE FALSE TRUE
47 nl CoPS unknown genus CPS onbekend geslacht TRUE FALSE FALSE TRUE
48 nl Gram-negative unknown species Gram-negatief onbekende soort FALSE FALSE TRUE
49 nl Gram-positive unknown subspecies Gram-positief onbekende ondersoort FALSE FALSE TRUE
50 nl Bacteria unknown rank Bacteriën onbekende rang FALSE FALSE TRUE
51 nl Fungi CoNS Schimmels/gisten CNS FALSE TRUE FALSE TRUE
52 nl Protozoa CoPS protozoën CPS FALSE TRUE FALSE TRUE
53 nl biogroup Gram-negative biogroep Gram-negatief FALSE FALSE FALSE
54 nl vegetative Gram-positive vegetatief Gram-positief FALSE FALSE FALSE
55 nl ([([ ]*?)group ^Bacteria$ \\1groep Bacteriën FALSE FALSE FALSE
56 nl ([([ ]*?)Group ^Fungi$ \\1Groep Schimmels FALSE FALSE FALSE
57 nl antibiotic ^Yeasts$ antibioticum Gisten FALSE FALSE FALSE
58 nl Antibiotic ^Protozoa$ Antibioticum Protozoën FALSE FALSE FALSE
59 nl Drug biogroup Middel biogroep FALSE FALSE FALSE
60 nl drug vegetative middel vegetatief FALSE FALSE FALSE
61 nl no .*growth ([([ ]*?)group geen .*groei \\1groep FALSE TRUE FALSE FALSE
62 nl no|not ([([ ]*?)Group geen|niet \\1Groep FALSE TRUE FALSE FALSE
63 es nl Coagulase-negative Staphylococcus antibiotic Staphylococcus coagulasa negativo antibioticum FALSE FALSE FALSE
64 es nl Coagulase-positive Staphylococcus Antibiotic Staphylococcus coagulasa positivo Antibioticum FALSE FALSE FALSE
65 es nl Beta-haemolytic Streptococcus Drug Streptococcus Beta-hemolítico Middel FALSE FALSE FALSE
66 es nl unknown Gram-negatives drug Gram negativos desconocidos middel FALSE FALSE FALSE
67 es nl unknown Gram-positives no .*growth Gram positivos desconocidos geen .*groei FALSE FALSE TRUE FALSE
68 es nl unknown name no|not nombre desconocido geen|niet FALSE FALSE TRUE FALSE
69 es unknown kingdom Coagulase-negative Staphylococcus reino desconocido Staphylococcus coagulasa negativo FALSE FALSE TRUE
70 es unknown phylum Coagulase-positive Staphylococcus filo desconocido Staphylococcus coagulasa positivo FALSE FALSE TRUE
71 es unknown class Beta-haemolytic Streptococcus clase desconocida Streptococcus Beta-hemolítico FALSE FALSE TRUE
72 es unknown order unknown Gram-negatives orden desconocido Gram negativos desconocidos FALSE FALSE TRUE
73 es unknown family unknown Gram-positives familia desconocida Gram positivos desconocidos FALSE FALSE TRUE
74 es unknown genus unknown fungus género desconocido hongo desconocido FALSE FALSE TRUE
75 es unknown species unknown yeast especie desconocida levadura desconocida FALSE FALSE TRUE
76 es unknown subspecies unknown name subespecie desconocida nombre desconocido FALSE FALSE TRUE
77 es unknown rank unknown kingdom rango desconocido reino desconocido FALSE FALSE TRUE
78 es CoNS unknown phylum SCN filo desconocido TRUE FALSE FALSE TRUE
79 es CoPS unknown class SCP clase desconocida TRUE FALSE FALSE TRUE
80 es Gram-negative unknown order Gram negativo orden desconocido FALSE FALSE TRUE
81 es Gram-positive unknown family Gram positivo familia desconocida FALSE FALSE TRUE
82 es Bacteria unknown genus Bacterias género desconocido FALSE FALSE TRUE
83 es Fungi unknown species Hongos especie desconocida FALSE FALSE TRUE
84 es Protozoa unknown subspecies Protozoarios subespecie desconocida FALSE FALSE TRUE
85 es biogroup unknown rank biogrupo rango desconocido FALSE FALSE TRUE
86 es biotype CoNS biotipo SCN FALSE TRUE FALSE TRUE
87 es vegetative CoPS vegetativo SCP FALSE TRUE FALSE TRUE
88 es ([([ ]*?)group Gram-negative \\1grupo Gram negativo FALSE FALSE FALSE
89 es ([([ ]*?)Group Gram-positive \\1Grupo Gram positivo FALSE FALSE FALSE
90 es no .*growth ^Bacteria$ no .*crecimientonon Bacterias FALSE TRUE FALSE FALSE
91 es no|not ^Fungi$ no|sin Hongos FALSE TRUE FALSE FALSE
92 it es Coagulase-negative Staphylococcus ^Yeasts$ Staphylococcus negativo coagulasi Levaduras FALSE FALSE FALSE
93 it es Coagulase-positive Staphylococcus ^Protozoa$ Staphylococcus positivo coagulasi Protozoarios FALSE FALSE FALSE
94 it es Beta-haemolytic Streptococcus biogroup Streptococcus Beta-emolitico biogrupo FALSE FALSE FALSE
95 it es unknown Gram-negatives biotype Gram negativi sconosciuti biotipo FALSE FALSE FALSE
96 it es unknown Gram-positives vegetative Gram positivi sconosciuti vegetativo FALSE FALSE FALSE
97 it es unknown name ([([ ]*?)group nome sconosciuto \\1grupo FALSE FALSE FALSE
98 it es unknown kingdom ([([ ]*?)Group regno sconosciuto \\1Grupo FALSE FALSE FALSE
99 it es unknown phylum no .*growth phylum sconosciuto no .*crecimientonon FALSE FALSE TRUE FALSE
100 it es unknown class no|not classe sconosciuta no|sin FALSE FALSE TRUE FALSE
101 it unknown order Coagulase-negative Staphylococcus ordine sconosciuto Staphylococcus negativo coagulasi FALSE FALSE TRUE
102 it unknown family Coagulase-positive Staphylococcus famiglia sconosciuta Staphylococcus positivo coagulasi FALSE FALSE TRUE
103 it unknown genus Beta-haemolytic Streptococcus genere sconosciuto Streptococcus Beta-emolitico FALSE FALSE TRUE
104 it unknown species unknown Gram-negatives specie sconosciute Gram negativi sconosciuti FALSE FALSE TRUE
105 it unknown subspecies unknown Gram-positives sottospecie sconosciute Gram positivi sconosciuti FALSE FALSE TRUE
106 it unknown rank unknown fungus grado sconosciuto fungo sconosciuto FALSE FALSE TRUE
107 it Gram-negative unknown yeast Gram negativo lievito sconosciuto FALSE FALSE TRUE
108 it Gram-positive unknown name Gram positivo nome sconosciuto FALSE FALSE TRUE
109 it Bacteria unknown kingdom Batteri regno sconosciuto FALSE FALSE TRUE
110 it Fungi unknown phylum Fungo phylum sconosciuto FALSE FALSE TRUE
111 it Protozoa unknown class Protozoi classe sconosciuta FALSE FALSE TRUE
112 it biogroup unknown order biogruppo ordine sconosciuto FALSE FALSE TRUE
113 it biotype unknown family biotipo famiglia sconosciuta FALSE FALSE TRUE
114 it vegetative unknown genus vegetativo genere sconosciuto FALSE FALSE TRUE
115 it ([([ ]*?)group unknown species \\1gruppo specie sconosciute FALSE FALSE TRUE
116 it ([([ ]*?)Group unknown subspecies \\1Gruppo sottospecie sconosciute FALSE FALSE TRUE
117 it no .*growth unknown rank sem .*crescimento grado sconosciuto FALSE TRUE FALSE TRUE
118 it no|not Gram-negative sem Gram negativo FALSE TRUE FALSE FALSE
119 fr it Coagulase-negative Staphylococcus Gram-positive Staphylococcus à coagulase négative Gram positivo FALSE FALSE FALSE
120 fr it Coagulase-positive Staphylococcus ^Bacteria$ Staphylococcus à coagulase positif Batteri FALSE FALSE FALSE
121 fr it Beta-haemolytic Streptococcus ^Fungi$ Streptococcus Bêta-hémolytique Funghi FALSE FALSE FALSE
122 fr it unknown Gram-negatives ^Yeasts$ Gram négatifs inconnus Lieviti FALSE FALSE FALSE
123 fr it unknown Gram-positives ^Protozoa$ Gram positifs inconnus Protozoi FALSE FALSE FALSE
124 fr it unknown name biogroup nom inconnu biogruppo FALSE FALSE FALSE
125 fr it unknown kingdom biotype règme inconnu biotipo FALSE FALSE FALSE
126 fr it unknown phylum vegetative embranchement inconnu vegetativo FALSE FALSE FALSE
127 fr it unknown class ([([ ]*?)group classe inconnue \\1gruppo FALSE FALSE FALSE
128 fr it unknown order ([([ ]*?)Group ordre inconnu \\1Gruppo FALSE FALSE FALSE
129 fr it unknown family no .*growth famille inconnue sem .*crescimento FALSE FALSE TRUE FALSE
130 fr it unknown genus no|not genre inconnu sem FALSE FALSE TRUE FALSE
131 fr unknown species Coagulase-negative Staphylococcus espèce inconnue Staphylococcus à coagulase négative FALSE FALSE TRUE
132 fr unknown subspecies Coagulase-positive Staphylococcus sous-espèce inconnue Staphylococcus à coagulase positif FALSE FALSE TRUE
133 fr unknown rank Beta-haemolytic Streptococcus rang inconnu Streptococcus Bêta-hémolytique FALSE FALSE TRUE
134 fr Gram-negative unknown Gram-negatives Gram négatif Gram négatifs inconnus FALSE FALSE TRUE
135 fr Gram-positive unknown Gram-positives Gram positif Gram positifs inconnus FALSE FALSE TRUE
136 fr Bacteria unknown fungus Bactéries champignon inconnu FALSE FALSE TRUE
137 fr Fungi unknown yeast Champignons levure inconnue FALSE FALSE TRUE
138 fr Protozoa unknown name Protozoaires nom inconnu FALSE FALSE TRUE
139 fr biogroup unknown kingdom biogroupe règme inconnu FALSE FALSE TRUE
140 fr vegetative unknown phylum végétatif embranchement inconnu FALSE FALSE TRUE
141 fr ([([ ]*?)group unknown class \\1groupe classe inconnue FALSE FALSE TRUE
142 fr ([([ ]*?)Group unknown order \\1Groupe ordre inconnu FALSE FALSE TRUE
143 fr no .*growth unknown family pas .*croissance famille inconnue FALSE TRUE FALSE TRUE
144 fr no|not unknown genus non genre inconnu FALSE TRUE FALSE TRUE
145 pt fr Coagulase-negative Staphylococcus unknown species Staphylococcus coagulase negativo espèce inconnue FALSE FALSE TRUE
146 pt fr Coagulase-positive Staphylococcus unknown subspecies Staphylococcus coagulase positivo sous-espèce inconnue FALSE FALSE TRUE
147 pt fr Beta-haemolytic Streptococcus unknown rank Streptococcus Beta-hemolítico rang inconnu FALSE FALSE TRUE
148 pt fr unknown Gram-negatives Gram-negative Gram negativos desconhecidos Gram négatif FALSE FALSE FALSE
149 pt fr unknown Gram-positives Gram-positive Gram positivos desconhecidos Gram positif FALSE FALSE FALSE
150 pt fr unknown name ^Bacteria$ nome desconhecido Bactéries FALSE FALSE FALSE
151 pt fr unknown kingdom ^Fungi$ reino desconhecido Champignons FALSE FALSE FALSE
152 pt fr unknown phylum ^Yeasts$ filo desconhecido Levures FALSE FALSE FALSE
153 pt fr unknown class ^Protozoa$ classe desconhecida Protozoaires FALSE FALSE FALSE
154 pt fr unknown order biogroup ordem desconhecido biogroupe FALSE FALSE FALSE
155 pt fr unknown family vegetative família desconhecida végétatif FALSE FALSE FALSE
156 pt fr unknown genus ([([ ]*?)group gênero desconhecido \\1groupe FALSE FALSE FALSE
157 pt fr unknown species ([([ ]*?)Group espécies desconhecida \\1Groupe FALSE FALSE FALSE
158 pt fr unknown subspecies no .*growth subespécies desconhecida pas .*croissance FALSE FALSE TRUE FALSE
159 pt fr unknown rank no|not classificação desconhecido non FALSE FALSE TRUE FALSE
160 pt Gram-negative Coagulase-negative Staphylococcus Gram negativo Staphylococcus coagulase negativo FALSE FALSE TRUE
161 pt Gram-positive Coagulase-positive Staphylococcus Gram positivo Staphylococcus coagulase positivo FALSE FALSE TRUE
162 pt Bacteria Beta-haemolytic Streptococcus Bactérias Streptococcus Beta-hemolítico FALSE FALSE TRUE
163 pt Fungi unknown Gram-negatives Fungos Gram negativos desconhecidos FALSE FALSE TRUE
164 pt Protozoa unknown Gram-positives Protozoários Gram positivos desconhecidos FALSE FALSE TRUE
165 pt biogroup unknown fungus biogrupo fungo desconhecido FALSE FALSE TRUE
166 pt biotype unknown yeast biótipo levedura desconhecida FALSE FALSE TRUE
167 pt vegetative unknown name vegetativo nome desconhecido FALSE FALSE TRUE
168 pt ([([ ]*?)group unknown kingdom \\1grupo reino desconhecido FALSE FALSE TRUE
169 pt ([([ ]*?)Group unknown phylum \\1Grupo filo desconhecido FALSE FALSE TRUE
170 pt no .*growth unknown class sem .*crescimento classe desconhecida FALSE TRUE FALSE TRUE
171 pt no|not unknown order sem ordem desconhecido FALSE TRUE FALSE TRUE
172 de pt clavulanic acid unknown family Clavulansäure família desconhecida FALSE TRUE FALSE TRUE
173 nl pt 4-aminosalicylic acid unknown genus 4-aminosalicylzuur gênero desconhecido FALSE FALSE TRUE
174 nl pt Adefovir dipivoxil unknown species Adefovir espécies desconhecida FALSE FALSE TRUE
175 nl pt Aldesulfone sodium unknown subspecies Aldesulfon subespécies desconhecida FALSE FALSE TRUE
176 nl pt Amikacin unknown rank Amikacine classificação desconhecido FALSE FALSE TRUE
177 nl pt Amoxicillin Gram-negative Amoxicilline Gram negativo FALSE FALSE FALSE
178 nl pt Amoxicillin/beta-lactamase inhibitor Gram-positive Amoxicilline/enzymremmer Gram positivo FALSE FALSE FALSE
179 nl pt Amphotericin B ^Bacteria$ Amfotericine B Bactérias FALSE FALSE FALSE
180 nl pt Ampicillin ^Fungi$ Ampicilline Fungos FALSE FALSE FALSE
181 nl pt Ampicillin/beta-lactamase inhibitor ^Yeasts$ Ampicilline/enzymremmer Leveduras FALSE FALSE FALSE
182 nl pt Anidulafungin ^Protozoa$ Anidulafungine Protozoários FALSE FALSE FALSE
183 nl pt Azidocillin biogroup Azidocilline biogrupo FALSE FALSE FALSE
184 nl pt Azithromycin biotype Azitromycine biótipo FALSE FALSE FALSE
185 nl pt Azlocillin vegetative Azlocilline vegetativo FALSE FALSE FALSE
186 nl pt Bacampicillin ([([ ]*?)group Bacampicilline \\1grupo FALSE FALSE FALSE
187 nl pt Bacitracin ([([ ]*?)Group Bacitracine \\1Grupo FALSE FALSE FALSE
188 nl pt Benzathine benzylpenicillin no .*growth Benzylpenicillinebenzathine sem .*crescimento FALSE TRUE FALSE
189 nl pt Benzathine phenoxymethylpenicillin no|not Fenoxymethylpenicillinebenzathine sem FALSE TRUE FALSE
190 nl de Benzylpenicillin clavulanic acid Benzylpenicilline Clavulansäure FALSE TRUE FALSE
191 nl Calcium aminosalicylate 4-aminosalicylic acid Aminosalicylzuur 4-aminosalicylzuur TRUE FALSE FALSE
192 nl Capreomycin Adefovir dipivoxil Capreomycine Adefovir TRUE FALSE FALSE
193 nl Carbenicillin Aldesulfone sodium Carbenicilline Aldesulfon TRUE FALSE FALSE
194 nl Carindacillin Amikacin Carindacilline Amikacine TRUE FALSE FALSE
195 nl Caspofungin Amoxicillin Caspofungine Amoxicilline TRUE FALSE FALSE
196 nl Ce(f|ph)acetrile Amoxicillin/beta-lactamase inhibitor Cefacetril Amoxicilline/enzymremmer FALSE TRUE FALSE FALSE
197 nl Ce(f|ph)alexin Amphotericin B Cefalexine Amfotericine B FALSE TRUE FALSE FALSE
198 nl Ce(f|ph)alotin Ampicillin Cefalotine Ampicilline FALSE TRUE FALSE FALSE
199 nl Ce(f|ph)amandole Ampicillin/beta-lactamase inhibitor Cefamandol Ampicilline/enzymremmer FALSE TRUE FALSE FALSE
200 nl Ce(f|ph)apirin Anidulafungin Cefapirine Anidulafungine FALSE TRUE FALSE FALSE
201 nl Ce(f|ph)azedone Azidocillin Cefazedon Azidocilline FALSE TRUE FALSE FALSE
202 nl Ce(f|ph)azolin Azithromycin Cefazoline Azitromycine FALSE TRUE FALSE FALSE
203 nl Ce(f|ph)alothin Azlocillin Cefalotine Azlocilline FALSE TRUE FALSE FALSE
204 nl Ce(f|ph)alexin Bacampicillin Cefalexine Bacampicilline FALSE TRUE FALSE FALSE
205 nl Ce(f|ph)epime Bacitracin Cefepim Bacitracine FALSE TRUE FALSE FALSE
206 nl Ce(f|ph)ixime Benzathine benzylpenicillin Cefixim Benzylpenicillinebenzathine FALSE TRUE FALSE FALSE
207 nl Ce(f|ph)menoxime Benzathine phenoxymethylpenicillin Cefmenoxim Fenoxymethylpenicillinebenzathine FALSE TRUE FALSE FALSE
208 nl Ce(f|ph)metazole Benzylpenicillin Cefmetazol Benzylpenicilline FALSE TRUE FALSE FALSE
209 nl Ce(f|ph)odizime Calcium aminosalicylate Cefodizim Aminosalicylzuur FALSE TRUE FALSE FALSE
210 nl Ce(f|ph)onicid Capreomycin Cefonicide Capreomycine FALSE TRUE FALSE FALSE
211 nl Ce(f|ph)operazone Carbenicillin Cefoperazon Carbenicilline FALSE TRUE FALSE FALSE
212 nl Ce(f|ph)operazone/beta-lactamase inhibitor Carindacillin Cefoperazon/enzymremmer Carindacilline FALSE TRUE FALSE FALSE
213 nl Ce(f|ph)otaxime Caspofungin Cefotaxim Caspofungine FALSE TRUE FALSE FALSE
214 nl Ce(f|ph)oxitin Ce(f|ph)acetrile Cefoxitine Cefacetril FALSE FALSE FALSE
215 nl Ce(f|ph)pirome Ce(f|ph)alexin Cefpirom Cefalexine FALSE FALSE FALSE
216 nl Ce(f|ph)podoxime Ce(f|ph)alotin Cefpodoxim Cefalotine FALSE FALSE FALSE
217 nl Ce(f|ph)radine Ce(f|ph)amandole Cefradine Cefamandol FALSE FALSE FALSE
218 nl Ce(f|ph)sulodin Ce(f|ph)apirin Cefsulodine Cefapirine FALSE FALSE FALSE
219 nl Ce(f|ph)tazidime Ce(f|ph)azedone Ceftazidim Cefazedon FALSE FALSE FALSE
220 nl Ce(f|ph)tezole Ce(f|ph)azolin Ceftezol Cefazoline FALSE FALSE FALSE
221 nl Ce(f|ph)tizoxime Ce(f|ph)alothin Ceftizoxim Cefalotine FALSE FALSE FALSE
222 nl Ce(f|ph)triaxone Ce(f|ph)alexin Ceftriaxon Cefalexine FALSE FALSE FALSE
223 nl Ce(f|ph)uroxime Ce(f|ph)epime Cefuroxim Cefepim FALSE FALSE FALSE
224 nl Ce(f|ph)uroxime/metronidazole Ce(f|ph)ixime Cefuroxim/andere antibacteriele middelen Cefixim FALSE FALSE FALSE
225 nl Chloramphenicol Ce(f|ph)menoxime Chlooramfenicol Cefmenoxim FALSE FALSE FALSE
226 nl Chlortetracycline Ce(f|ph)metazole Chloortetracycline Cefmetazol FALSE FALSE FALSE
227 nl Cinoxacin Ce(f|ph)odizime Cinoxacine Cefodizim FALSE FALSE FALSE
228 nl Ciprofloxacin Ce(f|ph)onicid Ciprofloxacine Cefonicide FALSE FALSE FALSE
229 nl Clarithromycin Ce(f|ph)operazone Claritromycine Cefoperazon FALSE FALSE FALSE
230 nl Clavulanic acid Ce(f|ph)operazone/beta-lactamase inhibitor Clavulaanzuur Cefoperazon/enzymremmer FALSE FALSE FALSE
231 nl clavulanic acid Ce(f|ph)otaxime clavulaanzuur Cefotaxim FALSE FALSE FALSE
232 nl Clindamycin Ce(f|ph)oxitin Clindamycine Cefoxitine FALSE FALSE FALSE
233 nl Clometocillin Ce(f|ph)pirome Clometocilline Cefpirom FALSE FALSE FALSE
234 nl Clotrimazole Ce(f|ph)podoxime Clotrimazol Cefpodoxim FALSE FALSE FALSE
235 nl Cloxacillin Ce(f|ph)radine Cloxacilline Cefradine FALSE FALSE FALSE
236 nl Colistin Ce(f|ph)sulodin Colistine Cefsulodine FALSE FALSE FALSE
237 nl Dapsone Ce(f|ph)tazidime Dapson Ceftazidim FALSE FALSE FALSE
238 nl Daptomycin Ce(f|ph)tezole Daptomycine Ceftezol FALSE FALSE FALSE
239 nl Dibekacin Ce(f|ph)tizoxime Dibekacine Ceftizoxim FALSE FALSE FALSE
240 nl Dicloxacillin Ce(f|ph)triaxone Dicloxacilline Ceftriaxon FALSE FALSE FALSE
241 nl Dirithromycin Ce(f|ph)uroxime Diritromycine Cefuroxim FALSE FALSE FALSE
242 nl Econazole Ce(f|ph)uroxime/metronidazole Econazol Cefuroxim/andere antibacteriele middelen FALSE FALSE FALSE
243 nl Enoxacin Chloramphenicol Enoxacine Chlooramfenicol TRUE FALSE FALSE
244 nl Epicillin Chlortetracycline Epicilline Chloortetracycline TRUE FALSE FALSE
245 nl Erythromycin Cinoxacin Erytromycine Cinoxacine TRUE FALSE FALSE
246 nl Ethambutol/isoniazid Ciprofloxacin Ethambutol/isoniazide Ciprofloxacine TRUE FALSE FALSE
247 nl Fleroxacin Clarithromycin Fleroxacine Claritromycine TRUE FALSE FALSE
248 nl Flucloxacillin Clavulanic acid Flucloxacilline Clavulaanzuur TRUE FALSE FALSE
249 nl Fluconazole clavulanic acid Fluconazol clavulaanzuur TRUE FALSE FALSE
250 nl Flucytosine Clindamycin Fluorocytosine Clindamycine TRUE FALSE FALSE
251 nl Flurithromycin Clometocillin Fluritromycine Clometocilline TRUE FALSE FALSE
252 nl Fosfomycin Clotrimazole Fosfomycine Clotrimazol TRUE FALSE FALSE
253 nl Fusidic acid Cloxacillin Fusidinezuur Cloxacilline TRUE FALSE FALSE
254 nl Gatifloxacin Colistin Gatifloxacine Colistine TRUE FALSE FALSE
255 nl Gemifloxacin Dapsone Gemifloxacine Dapson TRUE FALSE FALSE
256 nl Gentamicin Daptomycin Gentamicine Daptomycine TRUE FALSE FALSE
257 nl Grepafloxacin Dibekacin Grepafloxacine Dibekacine TRUE FALSE FALSE
258 nl Hachimycin Dicloxacillin Hachimycine Dicloxacilline TRUE FALSE FALSE
259 nl Hetacillin Dirithromycin Hetacilline Diritromycine TRUE FALSE FALSE
260 nl Imipenem/cilastatin Econazole Imipenem/enzymremmer Econazol TRUE FALSE FALSE
261 nl Inosine pranobex Enoxacin Inosiplex Enoxacine TRUE FALSE FALSE
262 nl Isepamicin Epicillin Isepamicine Epicilline TRUE FALSE FALSE
263 nl Isoconazole Erythromycin Isoconazol Erytromycine TRUE FALSE FALSE
264 nl Isoniazid Ethambutol/isoniazid Isoniazide Ethambutol/isoniazide TRUE FALSE FALSE
265 nl Itraconazole Fleroxacin Itraconazol Fleroxacine TRUE FALSE FALSE
266 nl Josamycin Flucloxacillin Josamycine Flucloxacilline TRUE FALSE FALSE
267 nl Kanamycin Fluconazole Kanamycine Fluconazol TRUE FALSE FALSE
268 nl Ketoconazole Flucytosine Ketoconazol Fluorocytosine TRUE FALSE FALSE
269 nl Levofloxacin Flurithromycin Levofloxacine Fluritromycine TRUE FALSE FALSE
270 nl Lincomycin Fosfomycin Lincomycine Fosfomycine TRUE FALSE FALSE
271 nl Lomefloxacin Fusidic acid Lomefloxacine Fusidinezuur TRUE FALSE FALSE
272 nl Lysozyme Gatifloxacin Lysozym Gatifloxacine TRUE FALSE FALSE
273 nl Mandelic acid Gemifloxacin Amandelzuur Gemifloxacine TRUE FALSE FALSE
274 nl Metampicillin Gentamicin Metampicilline Gentamicine TRUE FALSE FALSE
275 nl Meticillin Grepafloxacin Meticilline Grepafloxacine TRUE FALSE FALSE
276 nl Metisazone Hachimycin Metisazon Hachimycine TRUE FALSE FALSE
277 nl Metronidazole Hetacillin Metronidazol Hetacilline TRUE FALSE FALSE
278 nl Mezlocillin Imipenem/cilastatin Mezlocilline Imipenem/enzymremmer TRUE FALSE FALSE
279 nl Micafungin Inosine pranobex Micafungine Inosiplex TRUE FALSE FALSE
280 nl Miconazole Isepamicin Miconazol Isepamicine TRUE FALSE FALSE
281 nl Midecamycin Isoconazole Midecamycine Isoconazol TRUE FALSE FALSE
282 nl Miocamycin Isoniazid Miocamycine Isoniazide TRUE FALSE FALSE
283 nl Moxifloxacin Itraconazole Moxifloxacine Itraconazol TRUE FALSE FALSE
284 nl Mupirocin Josamycin Mupirocine Josamycine TRUE FALSE FALSE
285 nl Nalidixic acid Kanamycin Nalidixinezuur Kanamycine TRUE FALSE FALSE
286 nl Neomycin Ketoconazole Neomycine Ketoconazol TRUE FALSE FALSE
287 nl Netilmicin Levofloxacin Netilmicine Levofloxacine TRUE FALSE FALSE
288 nl Nitrofurantoin Lincomycin Nitrofurantoine Lincomycine TRUE FALSE FALSE
289 nl Norfloxacin Lomefloxacin Norfloxacine Lomefloxacine TRUE FALSE FALSE
290 nl Novobiocin Lysozyme Novobiocine Lysozym TRUE FALSE FALSE
291 nl Nystatin Mandelic acid Nystatine Amandelzuur TRUE FALSE FALSE
292 nl Ofloxacin Metampicillin Ofloxacine Metampicilline TRUE FALSE FALSE
293 nl Oleandomycin Meticillin Oleandomycine Meticilline TRUE FALSE FALSE
294 nl Ornidazole Metisazone Ornidazol Metisazon TRUE FALSE FALSE
295 nl Oxacillin Metronidazole Oxacilline Metronidazol TRUE FALSE FALSE
296 nl Oxolinic acid Mezlocillin Oxolinezuur Mezlocilline TRUE FALSE FALSE
297 nl Oxytetracycline Micafungin Oxytetracycline Micafungine TRUE FALSE FALSE
298 nl Pazufloxacin Miconazole Pazufloxacine Miconazol TRUE FALSE FALSE
299 nl Pefloxacin Midecamycin Pefloxacine Midecamycine TRUE FALSE FALSE
300 nl Penamecillin Miocamycin Penamecilline Miocamycine TRUE FALSE FALSE
301 nl Penicillin Moxifloxacin Penicilline Moxifloxacine TRUE FALSE FALSE
302 nl Pheneticillin Mupirocin Feneticilline Mupirocine TRUE FALSE FALSE
303 nl Phenoxymethylpenicillin Nalidixic acid Fenoxymethylpenicilline Nalidixinezuur TRUE FALSE FALSE
304 nl Pipemidic acid Neomycin Pipemidinezuur Neomycine TRUE FALSE FALSE
305 nl Piperacillin Netilmicin Piperacilline Netilmicine TRUE FALSE FALSE
306 nl Piperacillin/beta-lactamase inhibitor Nitrofurantoin Piperacilline/enzymremmer Nitrofurantoine TRUE FALSE FALSE
307 nl Piromidic acid Norfloxacin Piromidinezuur Norfloxacine TRUE FALSE FALSE
308 nl Pivampicillin Novobiocin Pivampicilline Novobiocine TRUE FALSE FALSE
309 nl Polymyxin B Nystatin Polymyxine B Nystatine TRUE FALSE FALSE
310 nl Posaconazole Ofloxacin Posaconazol Ofloxacine TRUE FALSE FALSE
311 nl Pristinamycin Oleandomycin Pristinamycine Oleandomycine TRUE FALSE FALSE
312 nl Procaine benzylpenicillin Ornidazole Benzylpenicillineprocaine Ornidazol TRUE FALSE FALSE
313 nl Propicillin Oxacillin Propicilline Oxacilline TRUE FALSE FALSE
314 nl Prulifloxacin Oxolinic acid Prulifloxacine Oxolinezuur TRUE FALSE FALSE
315 nl Quinupristin/dalfopristin Oxytetracycline Quinupristine/dalfopristine Oxytetracycline TRUE FALSE FALSE
316 nl Ribostamycin Pazufloxacin Ribostamycine Pazufloxacine TRUE FALSE FALSE
317 nl Rifabutin Pefloxacin Rifabutine Pefloxacine TRUE FALSE FALSE
318 nl Rifampicin Penamecillin Rifampicine Penamecilline TRUE FALSE FALSE
319 nl Rifampicin/pyrazinamide/ethambutol/isoniazid Penicillin Rifampicine/pyrazinamide/ethambutol/isoniazide Penicilline TRUE FALSE FALSE
320 nl Rifampicin/pyrazinamide/isoniazid Pheneticillin Rifampicine/pyrazinamide/isoniazide Feneticilline TRUE FALSE FALSE
321 nl Rifampicin/isoniazid Phenoxymethylpenicillin Rifampicine/isoniazide Fenoxymethylpenicilline TRUE FALSE FALSE
322 nl Rifamycin Pipemidic acid Rifamycine Pipemidinezuur TRUE FALSE FALSE
323 nl Rifaximin Piperacillin Rifaximine Piperacilline TRUE FALSE FALSE
324 nl Rokitamycin Piperacillin/beta-lactamase inhibitor Rokitamycine Piperacilline/enzymremmer TRUE FALSE FALSE
325 nl Rosoxacin Piromidic acid Rosoxacine Piromidinezuur TRUE FALSE FALSE
326 nl Roxithromycin Pivampicillin Roxitromycine Pivampicilline TRUE FALSE FALSE
327 nl Rufloxacin Polymyxin B Rufloxacine Polymyxine B TRUE FALSE FALSE
328 nl Sisomicin Posaconazole Sisomicine Posaconazol TRUE FALSE FALSE
329 nl Sodium aminosalicylate Pristinamycin Aminosalicylzuur Pristinamycine TRUE FALSE FALSE
330 nl Sparfloxacin Procaine benzylpenicillin Sparfloxacine Benzylpenicillineprocaine TRUE FALSE FALSE
331 nl Spectinomycin Propicillin Spectinomycine Propicilline TRUE FALSE FALSE
332 nl Spiramycin Prulifloxacin Spiramycine Prulifloxacine TRUE FALSE FALSE
333 nl Spiramycin/metronidazole Quinupristin/dalfopristin Spiramycine/metronidazol Quinupristine/dalfopristine TRUE FALSE FALSE
334 nl Staphylococcus immunoglobulin Ribostamycin Stafylokokkenimmunoglobuline Ribostamycine TRUE FALSE FALSE
335 nl Streptoduocin Rifabutin Streptoduocine Rifabutine TRUE FALSE FALSE
336 nl Streptomycin Rifampicin Streptomycine Rifampicine TRUE FALSE FALSE
337 nl Streptomycin/isoniazid Rifampicin/pyrazinamide/ethambutol/isoniazid Streptomycine/isoniazide Rifampicine/pyrazinamide/ethambutol/isoniazide TRUE FALSE FALSE
338 nl Sulbenicillin Rifampicin/pyrazinamide/isoniazid Sulbenicilline Rifampicine/pyrazinamide/isoniazide TRUE FALSE FALSE
339 nl Sulfadiazine/tetroxoprim Rifampicin/isoniazid Sulfadiazine/tetroxoprim Rifampicine/isoniazide TRUE FALSE FALSE
340 nl Sulfadiazine/trimethoprim Rifamycin Sulfadiazine/trimethoprim Rifamycine TRUE FALSE FALSE
341 nl Sulfadimidine/trimethoprim Rifaximin Sulfadimidine/trimethoprim Rifaximine TRUE FALSE FALSE
342 nl Sulfafurazole Rokitamycin Sulfafurazol Rokitamycine TRUE FALSE FALSE
343 nl Sulfaisodimidine Rosoxacin Sulfisomidine Rosoxacine TRUE FALSE FALSE
344 nl Sulfalene Roxithromycin Sulfaleen Roxitromycine TRUE FALSE FALSE
345 nl Sulfamazone Rufloxacin Sulfamazon Rufloxacine TRUE FALSE FALSE
346 nl Sulfamerazine/trimethoprim Sisomicin Sulfamerazine/trimethoprim Sisomicine TRUE FALSE FALSE
347 nl Sulfamethizole Sodium aminosalicylate Sulfamethizol Aminosalicylzuur TRUE FALSE FALSE
348 nl Sulfamethoxazole Sparfloxacin Sulfamethoxazol Sparfloxacine TRUE FALSE FALSE
349 nl Sulfamethoxazole/trimethoprim Spectinomycin Sulfamethoxazol/trimethoprim Spectinomycine TRUE FALSE FALSE
350 nl Sulfametoxydiazine Spiramycin Sulfamethoxydiazine Spiramycine TRUE FALSE FALSE
351 nl Sulfametrole/trimethoprim Spiramycin/metronidazole Sulfametrol/trimethoprim Spiramycine/metronidazol TRUE FALSE FALSE
352 nl Sulfamoxole Staphylococcus immunoglobulin Sulfamoxol Stafylokokkenimmunoglobuline TRUE FALSE FALSE
353 nl Sulfamoxole/trimethoprim Streptoduocin Sulfamoxol/trimethoprim Streptoduocine TRUE FALSE FALSE
354 nl Sulfaperin Streptomycin Sulfaperine Streptomycine TRUE FALSE FALSE
355 nl Sulfaphenazole Streptomycin/isoniazid Sulfafenazol Streptomycine/isoniazide TRUE FALSE FALSE
356 nl Sulfathiazole Sulbenicillin Sulfathiazol Sulbenicilline TRUE FALSE FALSE
357 nl Sulfathiourea Sulfadiazine/tetroxoprim Sulfathioureum Sulfadiazine/tetroxoprim TRUE FALSE FALSE
358 nl Sultamicillin Sulfadiazine/trimethoprim Sultamicilline Sulfadiazine/trimethoprim TRUE FALSE FALSE
359 nl Talampicillin Sulfadimidine/trimethoprim Talampicilline Sulfadimidine/trimethoprim TRUE FALSE FALSE
360 nl Teicoplanin Sulfafurazole Teicoplanine Sulfafurazol TRUE FALSE FALSE
361 nl Telithromycin Sulfaisodimidine Telitromycine Sulfisomidine TRUE FALSE FALSE
362 nl Temafloxacin Sulfalene Temafloxacine Sulfaleen TRUE FALSE FALSE
363 nl Temocillin Sulfamazone Temocilline Sulfamazon TRUE FALSE FALSE
364 nl Tenofovir disoproxil Sulfamerazine/trimethoprim Tenofovir Sulfamerazine/trimethoprim TRUE FALSE FALSE
365 nl Terizidone Sulfamethizole Terizidon Sulfamethizol TRUE FALSE FALSE
366 nl Thiamphenicol Sulfamethoxazole Thiamfenicol Sulfamethoxazol TRUE FALSE FALSE
367 nl Thioacetazone/isoniazid Sulfamethoxazole/trimethoprim Thioacetazon/isoniazide Sulfamethoxazol/trimethoprim TRUE FALSE FALSE
368 nl Ticarcillin Sulfametoxydiazine Ticarcilline Sulfamethoxydiazine TRUE FALSE FALSE
369 nl Ticarcillin/beta-lactamase inhibitor Sulfametrole/trimethoprim Ticarcilline/enzymremmer Sulfametrol/trimethoprim TRUE FALSE FALSE
370 nl Ticarcillin/clavulanic acid Sulfamoxole Ticarcilline/clavulaanzuur Sulfamoxol TRUE FALSE FALSE
371 nl Tinidazole Sulfamoxole/trimethoprim Tinidazol Sulfamoxol/trimethoprim TRUE FALSE FALSE
372 nl Tobramycin Sulfaperin Tobramycine Sulfaperine TRUE FALSE FALSE
373 nl Trimethoprim/sulfamethoxazole Sulfaphenazole Cotrimoxazol Sulfafenazol TRUE FALSE FALSE
374 nl Troleandomycin Sulfathiazole Troleandomycine Sulfathiazol TRUE FALSE FALSE
375 nl Trovafloxacin Sulfathiourea Trovafloxacine Sulfathioureum TRUE FALSE FALSE
376 nl Vancomycin Sultamicillin Vancomycine Sultamicilline TRUE FALSE FALSE
377 nl Voriconazole Talampicillin Voriconazol Talampicilline TRUE FALSE FALSE
378 nl Aminoglycosides Teicoplanin Aminoglycosiden Teicoplanine TRUE FALSE FALSE
379 nl Amphenicols Telithromycin Amfenicolen Telitromycine TRUE FALSE FALSE
380 nl Antifungals/antimycotics Temafloxacin Antifungica/antimycotica Temafloxacine TRUE FALSE FALSE
381 nl Antimycobacterials Temocillin Antimycobacteriele middelen Temocilline TRUE FALSE FALSE
382 nl Beta-lactams/penicillins Tenofovir disoproxil Beta-lactams/penicillines Tenofovir TRUE FALSE FALSE
383 nl Cephalosporins (1st gen.) Terizidone Cefalosporines (1e gen.) Terizidon TRUE FALSE FALSE
384 nl Cephalosporins (2nd gen.) Thiamphenicol Cefalosporines (2e gen.) Thiamfenicol TRUE FALSE FALSE
385 nl Cephalosporins (3rd gen.) Thioacetazone/isoniazid Cefalosporines (3e gen.) Thioacetazon/isoniazide TRUE FALSE FALSE
386 nl Cephalosporins (4th gen.) Ticarcillin Cefalosporines (4e gen.) Ticarcilline TRUE FALSE FALSE
387 nl Cephalosporins (5th gen.) Ticarcillin/beta-lactamase inhibitor Cefalosporines (5e gen.) Ticarcilline/enzymremmer TRUE FALSE FALSE
388 nl Cephalosporins (unclassified gen.) Ticarcillin/clavulanic acid Cefalosporines (ongeclassificeerd) Ticarcilline/clavulaanzuur TRUE FALSE FALSE
389 nl Cephalosporins Tinidazole Cefalosporines Tinidazol TRUE FALSE FALSE
390 nl Glycopeptides Tobramycin Glycopeptiden Tobramycine TRUE FALSE FALSE
391 nl Macrolides/lincosamides Trimethoprim/sulfamethoxazole Macroliden/lincosamiden Cotrimoxazol TRUE FALSE FALSE
392 nl Other antibacterials Troleandomycin Overige antibiotica Troleandomycine TRUE FALSE FALSE
393 nl Polymyxins Trovafloxacin Polymyxines Trovafloxacine TRUE FALSE FALSE
394 nl Quinolones Vancomycin Quinolonen Vancomycine TRUE FALSE FALSE
395 nl Voriconazole Voriconazol TRUE FALSE FALSE
396 nl Aminoglycosides Aminoglycosiden TRUE FALSE FALSE
397 nl Amphenicols Amfenicolen TRUE FALSE FALSE
398 nl Antifungals/antimycotics Antifungica/antimycotica TRUE FALSE FALSE
399 nl Antimycobacterials Antimycobacteriele middelen TRUE FALSE FALSE
400 nl Beta-lactams/penicillins Beta-lactams/penicillines TRUE FALSE FALSE
401 nl Cephalosporins (1st gen.) Cefalosporines (1e gen.) TRUE FALSE FALSE
402 nl Cephalosporins (2nd gen.) Cefalosporines (2e gen.) TRUE FALSE FALSE
403 nl Cephalosporins (3rd gen.) Cefalosporines (3e gen.) TRUE FALSE FALSE
404 nl Cephalosporins (4th gen.) Cefalosporines (4e gen.) TRUE FALSE FALSE
405 nl Cephalosporins (5th gen.) Cefalosporines (5e gen.) TRUE FALSE FALSE
406 nl Cephalosporins (unclassified gen.) Cefalosporines (ongeclassificeerd) TRUE FALSE FALSE
407 nl Cephalosporins Cefalosporines TRUE FALSE FALSE
408 nl Glycopeptides Glycopeptiden TRUE FALSE FALSE
409 nl Macrolides/lincosamides Macroliden/lincosamiden TRUE FALSE FALSE
410 nl Other antibacterials Overige antibiotica TRUE FALSE FALSE
411 nl Polymyxins Polymyxines TRUE FALSE FALSE
412 nl Quinolones Quinolonen TRUE FALSE FALSE
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More