From 5b5b95a47b90e77ee8fbda8cb898081e6ba87c2f Mon Sep 17 00:00:00 2001 From: "Matthijs S. Berends" Date: Fri, 12 Oct 2018 16:35:18 +0200 Subject: [PATCH] count_all and some fixes --- DESCRIPTION | 4 +- NAMESPACE | 1 + NEWS.md | 12 +++ R/count.R | 49 ++++++++---- R/eucast.R | 4 +- R/freq.R | 9 ++- R/join_microorganisms.R | 142 ++++++++++++++++------------------ R/mo.R | 20 +++-- R/n_rsi.R | 40 ---------- R/portion.R | 38 +++++---- R/rsi_calc.R | 9 ++- data/septic_patients.rda | Bin 30821 -> 30709 bytes man/count.Rd | 42 ++++++---- man/ggplot_rsi.Rd | 2 +- man/join.Rd | 29 +++---- man/n_rsi.Rd | 30 ------- man/portion.Rd | 23 +++--- man/rsi.Rd | 2 +- tests/testthat/test-atc.R | 4 +- tests/testthat/test-count.R | 5 ++ tests/testthat/test-freq.R | 7 +- tests/testthat/test-portion.R | 6 +- 22 files changed, 232 insertions(+), 246 deletions(-) delete mode 100644 R/n_rsi.R delete mode 100644 man/n_rsi.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 06b1d567..a531a7e1 100755 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: AMR -Version: 0.4.0.9001 -Date: 2018-10-02 +Version: 0.4.0.9002 +Date: 2018-10-12 Title: Antimicrobial Resistance Analysis Authors@R: c( person( diff --git a/NAMESPACE b/NAMESPACE index b42e9d62..c99c60e9 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -63,6 +63,7 @@ export(count_IR) export(count_R) export(count_S) export(count_SI) +export(count_all) export(count_df) export(facet_rsi) export(first_isolate) diff --git a/NEWS.md b/NEWS.md index c31a682e..a263e706 100755 --- a/NEWS.md +++ b/NEWS.md @@ -1,11 +1,23 @@ # 0.4.0.90xx (latest development version) #### New +* 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` #### Changed +* Fix for `portion_*(..., as_percent = TRUE)` when minimal amount of isolates would not be met +* Using `portion_*` functions now throws a warning when total available isolate is below parameter `minimum` +* `as.mo` will not set package name as attribute anymore * Check for `hms::is.hms` in frequency tables * 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 +* Support for class `difftime` in frequency tables +* Support for named vectors of class `mo`, useful for `top_freq()` +* AI improvements for `as.mo`: + * `"CRS"` -> *Stenotrophomonas maltophilia* + * `"CRSM"` -> *Stenotrophomonas maltophilia* + * `"MSSA"` -> *Staphylococcus aureus* + * `"MSSE"` -> *Staphylococcus epidermidis* +* Fix for `join` functions #### Other * Updated vignettes to comply with README diff --git a/R/count.R b/R/count.R index 10594fd0..3a22392e 100644 --- a/R/count.R +++ b/R/count.R @@ -21,15 +21,15 @@ #' @description These functions can be used to count resistant/susceptible microbial isolates. All functions support quasiquotation with pipes, can be used in \code{dplyr}s \code{\link[dplyr]{summarise}} and support grouped variables, see \emph{Examples}. #' #' \code{count_R} and \code{count_IR} can be used to count resistant isolates, \code{count_S} and \code{count_SI} can be used to count susceptible isolates.\cr +#' @param ... one or more vectors (or columns) with antibiotic interpretations. They will be transformed internally with \code{\link{as.rsi}} if needed. #' @inheritParams portion -#' @details \strong{Remember that you should filter your table to let it contain only first isolates!} Use \code{\link{first_isolate}} to determine them in your data set. +#' @details These functions are meant to count isolates. Use the \code{\link{portion}_*} functions to calculate microbial resistance. #' -#' These functions are meant to count isolates. Use the \code{\link{portion}_*} functions to calculate microbial resistance. +#' \code{n_rsi} is an alias of \code{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 \code{\link{n_distinct}}. Their function is equal to \code{count_S(...) + count_IR(...)}. #' #' \code{count_df} takes any variable from \code{data} that has an \code{"rsi"} class (created with \code{\link{as.rsi}}) and counts the amounts of R, I and S. The resulting \emph{tidy data} (see Source) \code{data.frame} will have three rows (S/I/R) and a column for each variable with class \code{"rsi"}. #' @source Wickham H. \strong{Tidy Data.} The Journal of Statistical Software, vol. 59, 2014. \url{http://vita.had.co.nz/papers/tidy-data.html} -#' @seealso \code{\link{portion}_*} to calculate microbial resistance and susceptibility.\cr -#' \code{\link{n_rsi}} to count all cases where antimicrobial results are available. +#' @seealso \code{\link{portion}_*} to calculate microbial resistance and susceptibility. #' @keywords resistance susceptibility rsi antibiotics isolate isolates #' @return Integer #' @rdname count @@ -47,6 +47,10 @@ #' count_S(septic_patients$amox) #' count_SI(septic_patients$amox) #' +#' # Count all available isolates +#' count_all(septic_patients$amox) +#' n_rsi(septic_patients$amox) +#' #' # Since n_rsi counts available isolates, you can #' # calculate back to count e.g. non-susceptible isolates. #' # This results in the same: @@ -56,24 +60,25 @@ #' library(dplyr) #' septic_patients %>% #' group_by(hospital_id) %>% -#' summarise(R = count_R(cipr), -#' I = count_I(cipr), -#' S = count_S(cipr), -#' n = n_rsi(cipr), # the actual total; sum of all three -#' total = n()) # NOT the amount of tested isolates! +#' summarise(R = count_R(cipr), +#' I = count_I(cipr), +#' S = count_S(cipr), +#' n1 = count_all(cipr), # the actual total; sum of all three +#' n2 = n_rsi(cipr), # same - analogous to n_distinct +#' total = n()) # NOT the amount of tested isolates! #' #' # Count co-resistance between amoxicillin/clav acid and gentamicin, #' # so we can see that combination therapy does a lot more than mono therapy. #' # Please mind that `portion_S` calculates percentages right away instead. -#' count_S(septic_patients$amcl) # S = 1056 (67.3%) -#' n_rsi(septic_patients$amcl) # n = 1570 +#' count_S(septic_patients$amcl) # S = 1057 (67.1%) +#' count_all(septic_patients$amcl) # n = 1576 #' -#' count_S(septic_patients$gent) # S = 1363 (74.0%) -#' n_rsi(septic_patients$gent) # n = 1842 +#' count_S(septic_patients$gent) # S = 1372 (74.0%) +#' count_all(septic_patients$gent) # n = 1855 #' #' with(septic_patients, -#' count_S(amcl, gent)) # S = 1385 (92.1%) -#' with(septic_patients, # n = 1504 +#' count_S(amcl, gent)) # S = 1396 (92.0%) +#' with(septic_patients, # n = 1517 #' n_rsi(amcl, gent)) #' #' # Get portions S/I/R immediately of all rsi columns @@ -140,6 +145,20 @@ count_S <- function(...) { only_count = TRUE) } +#' @rdname count +#' @export +count_all <- function(...) { + # only print warnings once, if needed + count_S(...) + suppressWarnings(count_IR(...)) +} + +#' @rdname count +#' @export +n_rsi <- function(...) { + # only print warnings once, if needed + count_S(...) + suppressWarnings(count_IR(...)) +} + #' @rdname count #' @importFrom dplyr %>% select_if bind_rows summarise_if mutate group_vars select everything #' @export diff --git a/R/eucast.R b/R/eucast.R index 8709eed4..69a7cf8a 100755 --- a/R/eucast.R +++ b/R/eucast.R @@ -507,10 +507,10 @@ EUCAST_rules <- function(tbl, # overig edit_rsi(to = 'R', rows = which(tbl$genus %in% c('Leuconostoc', 'Pediococcus')), - cols = c(vanc, teic)) + cols = glycopeptides) edit_rsi(to = 'R', rows = which(tbl$genus == 'Lactobacillus'), - cols = c(vanc, teic)) + cols = glycopeptides) edit_rsi(to = 'R', rows = which(tbl$fullname %like% '^Clostridium (ramosum|innocuum)'), cols = vanc) diff --git a/R/freq.R b/R/freq.R index dccb4783..be8410bd 100755 --- a/R/freq.R +++ b/R/freq.R @@ -336,6 +336,13 @@ frequency_tbl <- function(x, header <- header %>% paste0(markdown_line, '\nLongest: ', x %>% base::nchar() %>% base::max(na.rm = TRUE)) } + if (NROW(x) > 0 & any(class(x) == "difftime")) { + header <- header %>% paste0('\n') + header <- header %>% paste(markdown_line, '\nUnits: ', attributes(x)$units) + x <- as.double(x) + # after this, the numeric header continues + } + if (NROW(x) > 0 & any(class(x) %in% c('double', 'integer', 'numeric', 'raw', 'single'))) { # right align number Tukey_five <- stats::fivenum(x, na.rm = TRUE) @@ -351,7 +358,7 @@ frequency_tbl <- function(x, outlier_length <- length(boxplot.stats(x)$out) header <- header %>% paste0(markdown_line, '\nOutliers: ', outlier_length) if (outlier_length > 0) { - header <- header %>% paste0(' (unique: ', boxplot.stats(x)$out %>% n_distinct(), ')') + header <- header %>% paste0(' (unique count: ', boxplot.stats(x)$out %>% n_distinct(), ')') } } if (NROW(x) > 0 & any(class(x) == "rsi")) { diff --git a/R/join_microorganisms.R b/R/join_microorganisms.R index 6e54d110..35081092 100755 --- a/R/join_microorganisms.R +++ b/R/join_microorganisms.R @@ -4,14 +4,15 @@ #' @rdname join #' @name join #' @aliases join inner_join -#' @param x existing table to join, also supports character vectors -#' @param by a variable to join by - could be a column name of \code{x} with values that exist in \code{microorganisms$mo} (like \code{by = "bacteria_id"}), or another column in \code{\link{microorganisms}} (but then it should be named, like \code{by = c("my_genus_species" = "fullname")}) +#' @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 \code{mo} (created with \code{\link{as.mo}}) or will be \code{"mo"} if that column name exists in \code{x}, could otherwise be a column name of \code{x} with values that exist in \code{microorganisms$mo} (like \code{by = "bacteria_id"}), or another column in \code{\link{microorganisms}} (but then it should be named, like \code{by = c("my_genus_species" = "fullname")}) #' @param suffix if there are non-joined duplicate variables in \code{x} and \code{y}, these suffixes will be added to the output to disambiguate them. Should be a character vector of length 2. #' @param ... other parameters to pass on to \code{dplyr::\link[dplyr]{join}}. -#' @details As opposed to the \code{\link[dplyr]{join}} functions of \code{dplyr}, characters vectors are supported and at default existing columns will get a suffix \code{"2"} and the newly joined columns will not get a suffix. See \code{\link[dplyr]{join}} for more information. +#' @details \strong{Note:} As opposed to the \code{\link[dplyr]{join}} functions of \code{dplyr}, characters vectors are supported and at default existing columns will get a suffix \code{"2"} and the newly joined columns will not get a suffix. See \code{\link[dplyr]{join}} for more information. #' @export #' @examples -#' left_join_microorganisms("STAAUR") +#' left_join_microorganisms(as.mo("K. pneumoniae")) +#' left_join_microorganisms("B_KLBSL_PNE") #' #' library(dplyr) #' septic_patients %>% left_join_microorganisms() @@ -19,130 +20,117 @@ #' df <- data.frame(date = seq(from = as.Date("2018-01-01"), #' to = as.Date("2018-01-07"), #' by = 1), -#' bacteria_id = c("STAAUR", "STAAUR", "STAAUR", "STAAUR", -#' "ESCCOL", "ESCCOL", "ESCCOL"), +#' bacteria = as.mo(c("S. aureus", "MRSA", "MSSA", "STAAUR", +#' "E. coli", "E. coli", "E. coli")), #' stringsAsFactors = FALSE) #' colnames(df) -#' df2 <- left_join_microorganisms(df, "bacteria_id") -#' colnames(df2) -inner_join_microorganisms <- function(x, by = 'mo', suffix = c("2", ""), ...) { - if (!any(class(x) %in% c("data.frame", "matrix"))) { - x <- data.frame(mo = as.character(x), stringsAsFactors = FALSE) - } - # no name set to `by` parameter - if (is.null(names(by))) { - joinby <- colnames(AMR::microorganisms)[1] - names(joinby) <- by - } else { - joinby <- by - } +#' df_joined <- left_join_microorganisms(df, "bacteria") +#' colnames(df_joined) +inner_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) { + checked <- joins_check_df(x, by) + x <- checked$x + by <- checked$by join <- suppressWarnings( - dplyr::inner_join(x = x, y = AMR::microorganisms, by = joinby, suffix = suffix, ...) + dplyr::inner_join(x = x, y = AMR::microorganisms, by = by, suffix = suffix, ...) ) 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.') } join } #' @rdname join #' @export -left_join_microorganisms <- function(x, by = 'mo', suffix = c("2", ""), ...) { - if (!any(class(x) %in% c("data.frame", "matrix"))) { - x <- data.frame(mo = as.character(x), stringsAsFactors = FALSE) - } - # no name set to `by` parameter - if (is.null(names(by))) { - joinby <- colnames(AMR::microorganisms)[1] - names(joinby) <- by - } else { - joinby <- by - } +left_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) { + checked <- joins_check_df(x, by) + x <- checked$x + by <- checked$by join <- suppressWarnings( - dplyr::left_join(x = x, y = AMR::microorganisms, by = joinby, suffix = suffix, ...) + dplyr::left_join(x = x, y = AMR::microorganisms, by = by, suffix = suffix, ...) ) 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.') } join } #' @rdname join #' @export -right_join_microorganisms <- function(x, by = 'mo', suffix = c("2", ""), ...) { - if (!any(class(x) %in% c("data.frame", "matrix"))) { - x <- data.frame(mo = as.character(x), stringsAsFactors = FALSE) - } - # no name set to `by` parameter - if (is.null(names(by))) { - joinby <- colnames(AMR::microorganisms)[1] - names(joinby) <- by - } else { - joinby <- by - } +right_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) { + checked <- joins_check_df(x, by) + x <- checked$x + by <- checked$by join <- suppressWarnings( - dplyr::right_join(x = x, y = AMR::microorganisms, by = joinby, suffix = suffix, ...) + dplyr::right_join(x = x, y = AMR::microorganisms, by = by, suffix = suffix, ...) ) 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.') } join } #' @rdname join #' @export -full_join_microorganisms <- function(x, by = 'mo', suffix = c("2", ""), ...) { - if (!any(class(x) %in% c("data.frame", "matrix"))) { - x <- data.frame(mo = as.character(x), stringsAsFactors = FALSE) - } - # no name set to `by` parameter - if (is.null(names(by))) { - joinby <- colnames(AMR::microorganisms)[1] - names(joinby) <- by - } else { - joinby <- by - } +full_join_microorganisms <- function(x, by = NULL, suffix = c("2", ""), ...) { + checked <- joins_check_df(x, by) + x <- checked$x + by <- checked$by join <- suppressWarnings( - dplyr::full_join(x = x, y = AMR::microorganisms, by = joinby, suffix = suffix, ...) + dplyr::full_join(x = x, y = AMR::microorganisms, by = by, suffix = suffix, ...) ) 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.') } join } #' @rdname join #' @export -semi_join_microorganisms <- function(x, by = 'mo', ...) { - if (!any(class(x) %in% c("data.frame", "matrix"))) { - x <- data.frame(mo = as.character(x), stringsAsFactors = FALSE) - } - # no name set to `by` parameter - if (is.null(names(by))) { - joinby <- colnames(AMR::microorganisms)[1] - names(joinby) <- by - } else { - joinby <- by - } +semi_join_microorganisms <- function(x, by = NULL, ...) { + checked <- joins_check_df(x, by) + x <- checked$x + by <- checked$by suppressWarnings( - dplyr::semi_join(x = x, y = AMR::microorganisms, by = joinby, ...) + dplyr::semi_join(x = x, y = AMR::microorganisms, by = by, ...) ) } #' @rdname join #' @export -anti_join_microorganisms <- function(x, by = 'mo', ...) { +anti_join_microorganisms <- function(x, by = NULL, ...) { + checked <- joins_check_df(x, by) + x <- checked$x + by <- checked$by + suppressWarnings( + dplyr::anti_join(x = x, y = AMR::microorganisms, by = by, ...) + ) +} + +joins_check_df <- function(x, by) { if (!any(class(x) %in% c("data.frame", "matrix"))) { x <- data.frame(mo = as.character(x), stringsAsFactors = FALSE) + if (is.null(by)) { + by <- "mo" + } + } + if (is.null(by)) { + # search for column with class `mo` and return first one found + by <- colnames(x)[lapply(x, is.mo) == TRUE][1] + if (is.na(by)) { + if ("mo" %in% colnames(x)) { + by <- "mo" + } else { + stop("Cannot join - no column found with name or class `mo`.", call. = FALSE) + } + } + message('Joining, by = "', by, '"') # message same as dplyr::join functions } - # no name set to `by` parameter if (is.null(names(by))) { joinby <- colnames(AMR::microorganisms)[1] names(joinby) <- by } else { joinby <- by } - suppressWarnings( - dplyr::anti_join(x = x, y = AMR::microorganisms, by = joinby, ...) - ) + list(x = x, + by = joinby) } diff --git a/R/mo.R b/R/mo.R index 84303048..270fa0bf 100644 --- a/R/mo.R +++ b/R/mo.R @@ -272,12 +272,14 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, allow_uncertain = # translate known trivial abbreviations to genus + species ---- if (!is.na(x_trimmed[i])) { if (toupper(x_trimmed[i]) == 'MRSA' + | toupper(x_trimmed[i]) == 'MSSA' | toupper(x_trimmed[i]) == 'VISA' | toupper(x_trimmed[i]) == 'VRSA') { x[i] <- MOs[mo == 'B_STPHY_AUR', ..property][[1]][1L] next } - if (toupper(x_trimmed[i]) == 'MRSE') { + if (toupper(x_trimmed[i]) == 'MRSE' + | toupper(x_trimmed[i]) == 'MSSE') { x[i] <- MOs[mo == 'B_STPHY_EPI', ..property][[1]][1L] next } @@ -290,6 +292,12 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, allow_uncertain = x[i] <- MOs[mo == 'B_PDMNS_AER', ..property][[1]][1L] next } + if (toupper(x_trimmed[i]) == 'CRS' + | toupper(x_trimmed[i]) == 'CRSM') { + # co-trim resistant S. maltophilia + x[i] <- MOs[mo == 'B_STNTR_MAL', ..property][[1]][1L] + next + } if (toupper(x_trimmed[i]) %in% c('PISP', 'PRSP', 'VISP', 'VRSP')) { # peni I, peni R, vanco I, vanco R: S. pneumoniae x[i] <- MOs[mo == 'B_STRPTC_PNE', ..property][[1]][1L] @@ -578,7 +586,7 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, allow_uncertain = failures <- failures[!failures %in% c(NA, NULL, NaN)] if (length(failures) > 0) { - warning("These ", length(failures) , " values could not be coerced (try again with allow_uncertain = TRUE):\n", + warning("These ", length(failures) , " values could not be coerced (try again with allow_uncertain = TRUE): ", paste('"', unique(failures), '"', sep = "", collapse = ', '), ".", call. = FALSE) @@ -658,8 +666,6 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, allow_uncertain = if (property == "mo") { class(x) <- "mo" - attr(x, 'package') <- 'AMR' - attr(x, 'ITIS') <- TRUE } else if (property == "tsn") { x <- as.integer(x) } @@ -667,7 +673,6 @@ exec_as.mo <- function(x, Becker = FALSE, Lancefield = FALSE, allow_uncertain = x } -#' @importFrom dplyr case_when renamed_note <- function(name_old, name_new, ref_old = "", ref_new = "") { if (!is.na(ref_old)) { ref_old <- paste0(" (", ref_old, ")") @@ -687,7 +692,10 @@ renamed_note <- function(name_old, name_new, ref_old = "", ref_new = "") { #' @noRd print.mo <- function(x, ...) { cat("Class 'mo'\n") - print.default(as.character(x), quote = FALSE) + x_names <- names(x) + x <- as.character(x) + names(x) <- x_names + print.default(x, quote = FALSE) } #' @exportMethod as.data.frame.mo diff --git a/R/n_rsi.R b/R/n_rsi.R deleted file mode 100644 index eeffcdfa..00000000 --- a/R/n_rsi.R +++ /dev/null @@ -1,40 +0,0 @@ -# ==================================================================== # -# TITLE # -# Antimicrobial Resistance (AMR) Analysis # -# # -# AUTHORS # -# Berends MS (m.s.berends@umcg.nl), Luz CF (c.f.luz@umcg.nl) # -# # -# LICENCE # -# This program is free software; you can redistribute it and/or modify # -# it under the terms of the GNU General Public License version 2.0, # -# as published by the Free Software Foundation. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# ==================================================================== # - -#' Count cases with antimicrobial results -#' -#' This counts all cases where antimicrobial interpretations are available. The way it can be used is equal to \code{\link{n_distinct}}. Its function is equal to \code{count_S(...) + count_IR(...)}. -#' @inheritParams portion -#' @export -#' @seealso \code{\link[AMR]{count}_*} to count resistant and susceptibile isolates per interpretation type.\cr -#' \code{\link{portion}_*} to calculate microbial resistance and susceptibility. -#' @examples -#' library(dplyr) -#' -#' septic_patients %>% -#' group_by(hospital_id) %>% -#' summarise(cipro_p = portion_S(cipr, as_percent = TRUE), -#' cipro_n = n_rsi(cipr), -#' genta_p = portion_S(gent, as_percent = TRUE), -#' genta_n = n_rsi(gent), -#' combination_p = portion_S(cipr, gent, as_percent = TRUE), -#' combination_n = n_rsi(cipr, gent)) -n_rsi <- function(...) { - # only print warnings once, if needed - count_S(...) + suppressWarnings(count_IR(...)) -} diff --git a/R/portion.R b/R/portion.R index 7bcc229e..05f80fc7 100755 --- a/R/portion.R +++ b/R/portion.R @@ -22,7 +22,7 @@ #' #' \code{portion_R} and \code{portion_IR} can be used to calculate resistance, \code{portion_S} and \code{portion_SI} can be used to calculate susceptibility.\cr #' @param ... one or more vectors (or columns) with antibiotic interpretations. They will be transformed internally with \code{\link{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 minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA}. The default number of \code{30} isolates is advised by the CLSI as best practice, see Source. +#' @param minimum minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA} with a warning. The default number of \code{30} isolates is advised by the Clinical and Laboratory Standards Institute (CLSI) as best practice, see Source. #' @param as_percent logical to indicate whether the output must be returned as a hundred fold with \% sign (a character). A value of \code{0.123456} will then be returned as \code{"12.3\%"}. #' @param data a \code{data.frame} containing columns with class \code{rsi} (see \code{\link{as.rsi}}) #' @param translate_ab a column name of the \code{\link{antibiotics}} data set to translate the antibiotic abbreviations to, using \code{\link{abname}}. This can be set with \code{\link{getOption}("get_antibiotic_names")}. @@ -50,8 +50,7 @@ #' @source \strong{M39 Analysis and Presentation of Cumulative Antimicrobial Susceptibility Test Data, 4th Edition}, 2014, \emph{Clinical and Laboratory Standards Institute (CLSI)}. \url{https://clsi.org/standards/products/microbiology/documents/m39/}. #' #' Wickham H. \strong{Tidy Data.} The Journal of Statistical Software, vol. 59, 2014. \url{http://vita.had.co.nz/papers/tidy-data.html} -#' @seealso \code{\link[AMR]{count}_*} to count resistant and susceptibile isolates.\cr -#' \code{\link{n_rsi}} to count all cases where antimicrobial results are available. +#' @seealso \code{\link[AMR]{count}_*} to count resistant and susceptibile isolates. #' @keywords resistance susceptibility rsi_df rsi antibiotics isolate isolates #' @return Double or, when \code{as_percent = TRUE}, a character. #' @rdname portion @@ -92,24 +91,24 @@ #' #' # Calculate co-resistance between amoxicillin/clav acid and gentamicin, #' # so we can see that combination therapy does a lot more than mono therapy: -#' septic_patients %>% portion_S(amcl) # S = 67.3% -#' septic_patients %>% n_rsi(amcl) # n = 1570 +#' septic_patients %>% portion_S(amcl) # S = 67.1% +#' septic_patients %>% count_all(amcl) # n = 1576 #' #' septic_patients %>% portion_S(gent) # S = 74.0% -#' septic_patients %>% n_rsi(gent) # n = 1842 +#' septic_patients %>% count_all(gent) # n = 1855 #' -#' septic_patients %>% portion_S(amcl, gent) # S = 92.1% -#' septic_patients %>% n_rsi(amcl, gent) # n = 1504 +#' septic_patients %>% portion_S(amcl, gent) # S = 92.0% +#' septic_patients %>% count_all(amcl, gent) # n = 1517 #' #' #' septic_patients %>% #' group_by(hospital_id) %>% #' summarise(cipro_p = portion_S(cipr, as_percent = TRUE), -#' cipro_n = n_rsi(cipr), +#' cipro_n = count_all(cipr), #' genta_p = portion_S(gent, as_percent = TRUE), -#' genta_n = n_rsi(gent), +#' genta_n = count_all(gent), #' combination_p = portion_S(cipr, gent, as_percent = TRUE), -#' combination_n = n_rsi(cipr, gent)) +#' combination_n = count_all(cipr, gent)) #' #' # Get portions S/I/R immediately of all rsi columns #' septic_patients %>% @@ -130,7 +129,7 @@ #' filter(first_isolate == TRUE, #' genus == "Helicobacter") %>% #' summarise(p = portion_S(amox, metr), # amoxicillin with metronidazole -#' n = n_rsi(amox, metr)) +#' n = count_all(amox, metr)) #' } portion_R <- function(..., minimum = 30, @@ -273,6 +272,8 @@ rsi <- function(ab1, as_percent = FALSE, ...) { + .Deprecated(new = paste0("portion_", interpretation)) + if (all(is.null(ab2))) { df <- tibble(ab1 = ab1) } else { @@ -280,19 +281,16 @@ rsi <- function(ab1, ab2 = ab2) } + if (!interpretation %in% c("S", "SI", "IS", "I", "RI", "IR", "R")) { + stop("invalid interpretation") + } + result <- case_when( interpretation == "S" ~ portion_S(df, minimum = minimum, as_percent = FALSE), interpretation %in% c("SI", "IS") ~ portion_SI(df, minimum = minimum, as_percent = FALSE), interpretation == "I" ~ portion_I(df, minimum = minimum, as_percent = FALSE), interpretation %in% c("RI", "IR") ~ portion_IR(df, minimum = minimum, as_percent = FALSE), - interpretation == "R" ~ portion_R(df, minimum = minimum, as_percent = FALSE), - TRUE ~ -1 - ) - if (result == -1) { - stop("invalid interpretation") - } - - .Deprecated(new = paste0("portion_", interpretation)) + interpretation == "R" ~ portion_R(df, minimum = minimum, as_percent = FALSE)) if (as_percent == TRUE) { percent(result, force_zero = TRUE) diff --git a/R/rsi_calc.R b/R/rsi_calc.R index a89a31ba..83addfe9 100644 --- a/R/rsi_calc.R +++ b/R/rsi_calc.R @@ -107,12 +107,15 @@ rsi_calc <- function(..., total <- length(x) - sum(is.na(x)) if (total < minimum) { - return(NA) + warning("Introducing NA: only ", total, " results available (minimum set to ", minimum, ").", call. = FALSE) + result <- NA + } else { + result <- found / total } if (as_percent == TRUE) { - percent(found / total, force_zero = TRUE) + percent(result, force_zero = TRUE) } else { - found / total + result } } diff --git a/data/septic_patients.rda b/data/septic_patients.rda index 8879b5482e4ebf0d026c3b18bc8ddb0442037b69..c39cdaeab83a7ccd0e21692aacca596143ef9b67 100755 GIT binary patch delta 28773 zcmYJad0bN2`v-1ii>9TBq*zTV5Fj{$K-n^r3n&OCh=^!SA`&39sO>X@xg{tjizb*& z0uq>7C|cSwl}h4L;g(B#*`BR4&H9<2zwhsl-+A5Fz0Y~hJ;Y#oYzyvSf~PdX71l=5Cqq;^#LL%4{G#GHjz>)4Ih67` zNO{Lq`v2Da{}b^4$iPR3UFPKce?|Ytnj;s&UFPSzEOc@CwtD&hS7E_5*L+6)PjQ0P z`MsB2Tq<4Wt#Mf(c5#9H-?3(SzRSk^jSm@?NTy3YAYa~Cn&04FieLg{ZgBurOrkk| zOGA`YZ;64+E%Uq?1xO=;X-RgU&rF6RytgpS^+*@j6CG6@X_ps%UY5A!B4x=EFPy8> zj6GxAOxsFZuw~Sv+{edfRA|6asXE?>h_8kzJUzo)4@Zk|n`u}a7_%UnMyT}2=eqbW z*djb*cDa%0<K?!Dr6>f1Dygc%Mn^!bK(z(nl!p%v9 zY5f;by-hUmqWn8xzkHmFz(ufNi?ebORp+M#yEag`m8(xXPdnRjldEZdSlk_*G|u_@ z@NsS}*tKT_@v_h4czrkn1N_&6O4Y*uIb)olg+(1k{9*YkYc=r8W{U7_aLgcZ>Xa7O zf0%d5$A`8Ra9C6TDP2R#_i?M*>hu}?ZM6ZHzeusV(q&QM=v>=3lSc0>*s^HLqLQPg zqo-Zw8re5@y0dx9qQbxao0@lCx;yUgVSteH-W9RiU`usU_1?V~JMY}x zH&GE#@h)e}>`JF^Ulj#H!G{>94#?1&)}{4R`$vVzMJK!B;_~F7iQ7;^F}A4n>?#&h9=k+A9f~v0 zfHDS3sqj0-SMFA!Mw(1>i`Y*eEaWu60;?OVbR;=(#r$%ZgbYUnOE&EFc&kZhfHDG9 zvu_8Ij>U$^25Zyv`x*_tp^bTul{RQHyJ;7I*i%Sc zy1r6()H`UBF`+*ix$pkBOGmF}&>vpMq-Zjqy=u$b?DP4Qw7$_#2P_NN`l@wr&g#W? z|Go9)SkQdfx}v>q-$g`h*qZYO6(95Nn~2>x+kRSj|Gz>PQJALD{!b$(=khPyzm7jW z?YP7Dzg?);?5Arke_-) zTg#h%0`s~odeJ>v0jy9H=n;a|MH~V9i6h2sd+_zvz8=n-VpPm@kqwFHAvO> z+a;gR&;FC3%W_^VKmB3HkaAh@DkA6tn_rPYcYW*?5gp-Se9W#I8OarNYF319?bRJ&cR(jI;F!~D!*OFe}9?1;>G11<(BS`n`8Y<5o@wmZMR(ghUp+Lc*X1L zdk!X?MU|fJiXDCjSC~gvX!!pec=)Ay>Eh1M^QfOkdE5PEesA9<^UJd?@VK*EeetkA zF0XFBczfH|Gm5Qm>6U|te(nl}?L)<}mX{gtJ<@qafmok|nDx&ir0f6ve&W{BtM4Kj zq7utBZ)-N*gOsd%dBohQsmj?Vhcq%6OBGt5(bu5vuvf_a<2@CVkTYZ|Aw6RG(0A7v z$dbmVCC9_s|4R}TQ;z!vQ5QT(2%5hne?j+ijMwIazn_21I&HjqJoEjL+t%bWX%COQ z=WIFmpw|{Am8ZVAbG)lTTK2!>n`<9x|1rLY47ywR=l)r`{bCJs^?yfdWB&kjrJ<%5 z|NGDGgJm7kClYrbXHhG^?qAbUkB)KPI8vF;#Fbjj3R91sc4aZJ3X9uIp`$QE`>#fd@hWqxBy3ZO9KW;}?u{2O$8LI|0M!oEs zBJ@=rex}}L`m`GZT*)4H#|oMR&2DCN0B*FBT@X*n^fd@3;pcfqr#OucDbY_N zk%TP0hmt|J+6Jo$L8YZragO$!3wRJ@nyU!daqC^W6DW?Ou*w45Y?3Ik(mW2!%%ltY z#pOZL>!gA^Y^S6=Q=p$NxnDQZSynaFR4seE;Y<#r8UbkKo=*rqah#MDa-w zYZ8W-QLj=>^m_61_UJ{ZA&81BBnZpmyvaet0h3h%1(NB3K#CUcOAMgv9#Goh&m6Sw+65@TqD9NF^FtOO^CNSa|g7)nP=)w>`g_?brwu|MdLQ_5U z=H?o%3>|5~8>(`-?mI)@Z@QcYw(EN{bhuPmGZ<1RE}4cQr0#aBdC&?amB9#<&zHm! zziBL11h1@Y21pdfQ6*znN>+)Wac$j;I&&Wv4XVQS(F{pZ)l@QmpsAVQD|dh@(ydKZ z2JVHRy=_WL+1XN}4?M_STr@H5nuf56CFKK|blxg<7)Y(2%IuD7K%S(;sdo9FP zQKz(dSgxNK^XTA`?%jmJXUOS%>vAD?H_L6f1s7vG=`d*xn0nNB1<& zUvKZB+jiFF3}^C?@#!;aa_PiWysyes3t^Y)NIDlAY0xJ+8J4!I_ zQ3Vqk*tYCw!psFig(PoEEtXhYGoeY8P>I!n0b5D#_?#B9MfU<>!dpA+*NGjSlDz3% z$tlb8m~;Ni$~dFz|=c z@1tsZU8S=ZD;r4tup2v!Q$YqgnKYq32`l9XU@=fV(3(#nC<5yV07nNk3vL^t-6DtO z?n*T|y<=(vAbrh5@O0Ia%K;0mZpJ2_fkTe7k%2PaT$?dVJwCPwXo>)086c>H$K=3L z1MrZNc&fj4q?$}n06B9ODz?T^*&^N5H`79!B@3N2>@2+mfuka$2fB4}73!}}~T4_B8f zNxe3aBQpt!BDxOo@cy-Nq$LQW1L0BSiHGpynDZregic;YPrK9}z#XK)Y}~AX0MNv+ zgxiQOlY$sFhB(zUV|&xsnGz~`rN^Z$K#jztD%)u12RUdz<3z`d#GXye&e3!g2ko&g9`v$q2%wue?fu;Eg5^we%~}o9|f5NgW~31{f^HuF{6%N-rqx zXoip&hMjI@l9s6loexfjHEE+UUP`LWsP$5* z%CQQa4;(U1tudmsT929{LRl8T;TC}4`WGTl<54{fb}KVVSilL6VOEzghkRl2#5Q1` zDj6JuXs8U1s^wy|%}aDa@M+?M{WH=FS}Qo72pjBJ3Si+gFxFHoS4Xm%vtZ?7jVRm` zOohpP$fP1ilQ!OU|7616WfAwDoK8<5bM{nJe0o^`d02lX_;A;F$Jq(iSmTwgiNRzm zX;eg`^Tw~NG*84sVG~n4qLtJn@efJry4PBpwt_H|TH>hZW!Gw}Kq=CFEwum!T!?8@ zC`GV22`W_?>B71!*eKg6){#AVMU_q2q?R|0&u7x7H(c^n zYLc-dc+zm~!csGZ91kPhV1cvnYO$z{s(>(M;+pGbE7xgl;@+tm${W?m4X_>+t2eu< zQvuBc_X=TBPCQfA-ooi@X0U}e-DtHTGi6;!RQAbng2w1r**rYV9N?NK9OK~9m}N^f^7#fco*2ph{G<@pOb2uNocXSS=Obc~!$3OTTE@_2GWG9Yhh z%dF+rt{0~Q-(~eZKh{FNQ%CU)Ih8?Qw((LM=4QqlOAV=Ab2_%-=E{9H;fm0zC5P6o z+x2SK?1sIo-1lxJ-pSqc`RLAl3!I}l2^u0h!_5spdh&k8YVVxF_?#^lUsRnUMubXd z-5Y0($)nrueY_o*UYD1%u@=20M4baavuf+=;9Y>Ni}oi!Ia2VNx$TBW-ThUQPnPOa z612lFLXTARGgQfs_aC`Fa(~ahOBE5mq2!*Vk!|U(J8!OP2!z|h?k^3zb$IYb(>c(^ zJmvlu24xmGy&>%ES_ta}Q`S0rDB^IJ&MZy#b*)sQSO2#ra^ZrYyL=pu$TFtNC=HWd zRjYpb3@??(4F^L=hPmAkJf?D}JQay0`!Rf=K(_)PVK6vul3X3_H~AuuGv5Y>t_fan~hS$XLA;~at+Q90J@+88Jh8mNWEG3nv0yRBV zP#Th~o5{0pX?eFFL!zot{s;E-f;3cPOcmySzs9Xvz^4FJyk1f~J<4Ct*Hk;mfQ+E( zNbg>+h#_{Va>e|Xm@WOj`6w}%5f7sIWOV)Z;2?>wO>FgpUEUUm4+jI)RC|_dIZu}= z14Lr5F-|iLQMpJOlPF4UrQv0p_RCtCx|p^5XEI}IK?FRA?8y}$NUO$*nTL8O#t}*) z%DV0HvkN+!o)6R>!rO;6B|IQM+DC#d421NnNMyZ9#2-Ab6EHFZ5OthLc6*H5=vhs2 z?9zA~0#XZE67HdkMr6Qh{p0u=Q$~XiN(3Jql2RCsE#jJfHcG|2MmDh>4cL+!BsCTN z>P=b3$^rk9JIrfYc-&wUNr+v#MxdmjhE7kEgziVRewv+qS&RS{S@3FL z)>2P2b%%w_Q#05QvrvH|qd~Z81B@@E?~?Q}Fc3tHAgh(Pv4yRHB;hrD3PXBeKX3w! z9a3qUS}S`=@^GN0?2?`acls-cFN>bfR@ZNMp2la~-WPOdBDIhQat-TbWg4GKIyYksLgeMwi9#CL7~w z#C^d$YBd002*gTzT}?7PQHH1uq+#kc0wt;;0H!G@7xae{vO!e3Si5%9%!30t=~K^m z)GELdQ+zmcK1c_JX@Mdd+2)Vs@gHo&u}1(JvJRJ_Xmd zlARVAPPdc}l@iGaH(a8KkOVXwIF)_ra{n5sAyXhjvB&2o2(BNBz>1P$NHmz!Qe%lG zGk^>_UwlK&HClN?H8d!+7^$YJVUt0FS77&b#nHH|@&=;nRGqVY3_+)=qY(%^YFMOl zHd)M-7+6`DRdoYqGzo?^I#i;DPO?1ZZ?L{lZ$>5omWZz)4mJ~#& z9M7=ucv7<+ZD3Ejs~pTKgJ4XHNI{;}45i}vmpa?QX!)q<+_%`gjfaMw^-+WbKDo3F zr@)dm3`ZLSl?n00k>L?!;rdF6;Fl;q&>{3%Hu z@?ig3N+uMH=p5__0re_WlX!(+pA^`TgaObSyh|krveh`sDv8vW2Wk`?Jduxeir@tn z$nNNAl`4hg`|zh*xhmURwOe9>0%UTn-w*zy0Lew%TAdTapNg z463AtmJeV3rqy zI$8`I^ubt_wFsD}W$CJQNvSdB4jP@QVu&bsU+xGl8PPm9(+22d!8Ayvm-o@Ns!=A- z(aPio`*}3Pc#}-r%r!QK$b%=xF(|1zW%Yqwbg~bHF-7w&^WDX1>2H8fDR?#}tJg*m zi)8TOL^5E6Zk$pus+tF?ovC=Bu9s9zDojGtc@84o8W3ZR2bV+JVWX|&ERbNQWq*gF)GfUPN8Hy)_lqTcIAk^=5O-kQI@ z7*fPm*k4u*o5s-UR|N1eI5g-ba`mD4{~2_d+ff% zt~WX0irGB}w#e=a4_DocP%S&OEKi*m?Vxv>$Gm1UK5p8y)yuPJVzIa=-|v58OM;q< z{R#@M@_|y>H~VZ}aXC}31E1R%rSJnU=dc6ff+tt|=RGsfSFrq+l+K^mrH@Q@0rahv zJ$&1hU*PAWBr<=!zkBBAUjy#vpL*D9CqpVLd2w9ix8Z}wm;O65|DIQ5ug6{Cm~rz2VICzDGNrc<-ebalLh)Pq{JF7pdcIr^o}$dydq(xm@rJ{ zB8JoNdUzmNrsT%Zz)Q?pKYsqWt1-yWF%MU?rkfPJrYHlT6G1Zk=2HQD?-;&N>o%_- zah_|84$~23r;)AZf>w?S4@rhXCKp}La+OEVv%pdP4z^vN1S0(H$(aSPtwtxTBU(!K zD+KYwvfTuubmJ)0&)6ChQ(Xq!!oifnyj^Py-hLiO3*gS6Et=FCc`&JfF+VuYuK+** z$IzKTNJdS$QKM8{pU;bv(}-^QW>2j)E)uZAd%ltC;{!rvcu1n+gzzA$KMf>9(F0xQ zwq^hWwJg8~4hRlxgr9bm%4GA1L~lTt3L*>K_{c}#cJBHI@%%%V{%pDT&+&E0k;ykd z7?u-jVxtnU~9l{|W}IP|}`=QNkVLc#O*X{2qU+)WW1ZbkpNert32%4CqC ziKUcPx`H08dehZ?W%^C^x`e^JLlysxMSt2)c$Tv9blV5-Ka)?K;i^tbAL_~vuHXN6 zMe46w;l_8YZRRAVoavvGob~*y{(h_O)%L1T{BNOyXLgPGu&xfb)9#lccW$=s`r35) zebnuCeD+qviP??V?>-;Iplzx4*drRzG!A`GamE!TSyW{oqrir$vz>4jwkH_cC9NF-W+%?D;O*f4N zf@Ur?{cmH+;01h9#Pq@H@#zCIm{LyG#yIito=|QG>i70H9#5X8>fgP%*H!hCePfB8 zxmLspADwBx{Gqk3v!SX%Z+iNZ>P1L&dcmQ(GpT07ldl8A?{n8(eYz<@N;910s8^oJ zz4&bJUw`fD?JVtA@XJ&15Bd#hwO7mO`kI;E6KL`7PTk#wsiLv&7bz*LxQK3c$N0S_ z=entT`(`b)GlIKgZHlF5Hv&U#=aTlX8dqIBad}F7=~gPvyxqI}K>N_AlaDG)fb7Hj z7Jn1-L)Pw$_Yv=?duAlfZ_DQVUhlNk8Ai+z@Zp5^?YibR(GL6L&gD%fHd>F|T*bPm zX?%?dMX^f%VY~-7d{RCb{`w@S`LL$9Jz&K0TSA(yt}cb*B^HS>}3Vy&=kV@ms7;5)w`rMVYX!t$m9 zJ0jKo?&{E?gps7a$+`oV^R7fZc%FT1=K00(sD93Gm#6M!J!y+wEu5zLuGln|W8b;# zT(-so^|@L5QV|_c=-qK!8 z5v08?dvNE$UR{#6Wj4EiTr1@@@7lMAUuQF+o4&HPTNX^+-c-!n*?XzwTtLOeUw7`# zqs2bofN=BMWZk}bn@;cdXxXUm>c$c$f1`z6w|o-pN=s@udvU0R!Du1JhqK( z`+E2Rx>;Fj?M>;LJvdf^GhIl_$ZQ-(bSVS2bKhifHXq!q@06u8>k{5HJw6vfp8fQ} z8vh!f!1>a-?x(ztso_hvz*D=D_xiWDtFD~Eo@G5~{P^o2>aT?Mdq2Oq*H`!W(nJL(*7F{I$y!g#a&oI#7l-HlkXxzuI`#B-q!y@DdL<| z{qyt4=3VzWucv3;Pnaw*4$13p4}a`9Cv4Ep@qf}~@X4|iCTy%oKR$D*toJn$dtBQ0>&y?b zKXkWbx07Gw9k_IhK2tNo1|;qmUb?N-@`p3VQZ-4xUamUyF`@We|NEF3VTcWWeqa2O zACBc0p|~$HvSQsv-+P9{ro`@(p#MTciuZxO+4G-5R+NQKi&?m>=(RDFHO7;N!;>e+ zs(PR<$z< zR3l(?rj6;hm1eDEcE=#DwDVgMb9ecmDw}sj_q45@S=Or=Zuc`ruYVYOsKh@hd+Dpa zr46*0A~x{nRSlE}2sTP<(R?~X|`J>6&6#j(t; zOBnY>_4l(bTik#8F7AnWTYMvW)uWv`zQ?iK_ZXV`+hYxYvU}ry9-I1i)jOrAcPz|^ zuD^Fs8q(~(VeIvf%o(u0F_{ydQbVs6jC?wGfVCgfZ}PiQ8U@Rd!IG%?vN`pwm}pgB)Btp_lwtt zvkdv0C5`O|gog*)+#N5AgWMm|<_;IVb#<*c#=$gy!SU?z6IW^i*=bu)zp=ot+6khWo8)BJl+wT=6a|B^5;fLFHB z`<`-DiYwbS#uZhD&Am;R6L;S@yJ@m@a~byEJ)(0`b7S(^64bdLFvSfM1J7sv=ZrN3 z{Q_>kY)gqjZbS|aRsH;H>SKq_qrKMQiK~5eh~jLl%KkU`5l=r=IR7yx`MYLwV}FQ; zQn2b^AXO-jxeRb}ft3fdh3xq23Y+wf;9MZEygu&R$Me^d3V{mL77 z=EIajFaJ1@k36;BC1%kQxywEx5V&R2n|VJdHp#Z1a8Yi0w)K{5;G2&X-ZQ7qjF%0c zIy~>-YTzv_$F(#LzX`j9v-ZgD2VdVj-SkgR(E0(|cD}UeMh5v0JN4Ua-R)I=&f2T+ z{f+S(u`{XgY)&7hiYKP(do zDUDMtJa~ycOH;3Zu$Y&tFa*+17}27pmupGu4|(8vW=_ENAfpZuw`BPeE53i>hFpDx zewpw9r9=(>xg)B)`qG{x$_w$mBYIHvi`?ozrx$pZ|NKO1Ox}2aI~CaNE~uKE@YW=M zsq5J9u}6=2RqW*kL?c5LwiTL~%jAIb?#E@H)=x>Z=Jl@RN>@g#3E-a+i*DwKk1ft! zwer+rR>EWpG~1|LaOET>fQIp3LY}|nL1E$ozp4-kXQ2t3)z~?^>yuMM<Ivp13CY=^04WTjITX`D8pkVCC6WODY67~nu@`(6NEVD^ z%;R{N){q%_7Uv9W!w?k)x-A=P?{)a5L=hQnJw3S6}G_J3u%Ia0tvw z$|%k$M8ar)kvITCgEegoc&c=tBMwB8q4Y#53X;iCafI-CgS)lZ|A`BTYNYewflDe=(x z;rbYduofsbi>R4`EMr4>d}dsYfp^`zq`EACdZP-B6x({F_F&%Fq8)=|A;#aop;{jg zbGDK_bWD*1Nyj<4WH!avsPMId6v7}2hHeAd&7-VnfmPu*rMEVN<6)@O>Z!PnkW8!s zeBNXT0QOHz!CP50D+f<%Ct5kMYHKnmo;$asP~@sHoYf|p77=3YAUq6=37NPo8c&J{HnStA3Ejo>u zbJG;XGkfd+r-_W}ao~(Byb(Tl+D6rztxO>%AR``JMjgk8jfypb4#<#_SQ|#y+o_Q; zCY3Chk&Oxx`!%$Rq~g&cZ;ihMXZ1d9)}AlXR`zLipkeNo3Lp>EXAV*Ct9T7H(!GyvcXd=5YL*X}Jm4Hhv zD5!!PEkYCNzG4~OSIvnh+tR$P?ND)Y0Q+o!lxVcE2o(LeePWb#dXx^Eh$ey!Vi5qL za|C3P=2UOADpTysAQh7Ian&5GuzVUcH!SAyB&hsO$rM^)sdbkmj_|BaBD`EJQNWy} zQ3*q&Xcd#pXho{BBa7E0DdXCkhC~XzBa;VjjHmXhjN=9E3+s78PhKdPIix@m%SdyP z3T0qpvwY6e<40~o^TvE3)zy6NX??tZEmv#e34NF10$6S7h;{R&X{m%>7G<2Gu(l>Q z4e&Y$s7$dW&Rb1y23yqO}=9E{v8@_)3 zEnQ%dnk;yzK|}yBLgGf4qIvi>q>e5pOq8Wol}^@j3t2+-A{otUR=@}QX{E!Qm`V2_ zXMTexu-KaiB_h4e8U+FA6IZWA#y~h|U^R9@xa&C8iYCgvm6>EKvkIgPveUo{Sb;9n zOKb3|KMG6o0aDxocck)7nh~rtHH=&@rZefJ)BRPljF_WTYg;(KjbGE#y%dIMgW>w+ z4L-yqH#ni1)a$KUV)v#><`E5IUlkf^00F3G8M7Y}pTrZIqU@?*qB5%8Z=zCJ(-@zW z6o3ty)cJ=oa5~jBfx}v<6HNO#lCXM*Qch!%^s4a~cVx8`6oQ>J(=Bmyf`dbujEd`+ zTi3{Xg(6c}uJLhW=#1^u2@6(;(`mV_nPeDMAg6JAjT0(uTzw*`hE=L4Z;;;^f@*Eh za0uDh!H@Kbp$nDG*|vw&?~x^SGz6Y?0Nb z)7$YZq*Fd-HTHTGjQ7w59h4rAg42wGn3%-*A0wq+zwHlxX`W!%aXdam32fC(y}A3d z`{&){v!GE9T0sOmB>`Yn2#`6z9%bR!V~Wyd)p-e7og9F*v3l9lT)26fq|ml9qOn6~ zq2`WWy;V;zcHB_vtw{)t4zpt{z;_|Z76)>g8}SOkm^@z0YsBrC!1;o-mMXne->CMIWxL}N5J^4I8ub8nu7ES*ww z+p+d0l5q~;C(ET46^lPXm_rFWCh;AVUM&Yt9Y>=2vEpp*a5jxVhcWHsIG=7C>% z6)%z-L?M|Xl_C{Q^i>Trh&CY-UbM#ARO<`WnvB4~9yO#qGoH%AbEj}=k?anFeK?!j z4sKPyy_k*on6 zyg^`qjrWS_BB!+>1dA*>%WLLNR<))Pg}ByU-q}T}{+Iz`_*}ou(*m<1DT{;efU7Jh zrPKh1Pubgj&tgMBlYnv6bWCyp*n&1TQhN0h$hmkJgE$+6mMj!kJ8c{S-c48}Y0VBm zWRtd-+damC9nth1qp6x9iyOw^XW-W~Wuhk01#&b#w9(Wd3r<;%2m%#Qt39o3J<0)}iYJGMN9rBT-mTSq zr4sBGnB_&%!z6yCyi{Fg5QgV~X`xz@)>ci#dmH@Q1Rct1^_(`&MfxBJajh&|e*?+~ zCay8xNy1ja;(=5$k3RQ7$AJk>V>7}K4sFm30S2Xm#`A-7GAONJetD4u8c7<`Aqufs zi267=T-DE?T)?w{Yn;NOA>0j5f-!#@)`rH~kHT-nKzXg~vdpxF%>-C8 zsP9G-0d#I_m2q@{YO3YpYV?TUOd1l4GUEERsF-#D$>0Xjm{RrSM3U1_g_4@|J(M(9 zjEaDOnnuW4o-cf|l^A1+QbcM@Jmav?U*c!Q4H}|`%HXYbp}%I3uL%yMGKko!HNYFG zaGXV7Qz;V?l6X3DrGt`1?ZJl=1jC8-Fm+t&ns5(mc>@GeItc3pl)!i+RE%6K){KMH zlxl6wTtrM?xs*|l!K!(5N+OI)=ox|Z2`NH1ye_6bvDORM8M&a0!{+%;SST&APq!~Nveqo7ub|UjlDHIQIr$~mg(el1ggxl=zL8B zx-1-#+Qt@A4MZ{&#v4pUlsdyHaYj-AgrqePl^~D)um+q_C1R8XiTSG37(W6bQRS`W z$@n$KJK>lpRLm4i0#-9fSyq829>~cMbF@YzyeR|4H5wZ*B)dbZk}FLZGJ_JA1|Pzb z`t53jdhT)7s6hsdiyciyXjvqUuE+-wo`tB^X5pAZFuOmHI;bCX)nfaSgmdU*n2{35 z6PD^+APz-wwY#v~QLSdT1=fQ5b#ixxcv!16F*RD_XqJ18OvflSIt}rV(}^l8lvaD}}r)h*74~HksK|6j}ow%-0gD3GBf_ zK0h-lJgP`*yrb1{3Bz=Ti0s;+W7OarNgfP=jMUF)z*Vx_;&HfvMefKL;|OqyLuKzggq_d0-SCHY^I-->@}DTtV9LRC;LT3`gkla4(pP;SM=ro0f+;TT`G&pUH5U0 zZ}MM10qlO<9Zu?=x20y-%#B&R4$^mbk4Jf3ZHF~)p4ZC3>4yV54)(2aIW^8GoJnUquk&<$8YWY4c;x_{r&UzAOEI0io@Dx&7dn^ zuMQ~Fmqy*b;%wjVd6)g}yza-LjrEj?f3H2RU#4UDaGyFNyK5Ix^^7dP8)5aqEegS= zy~%2~m)CyVDE--Y(OU9V`sTQ(o9q2f?P;J7mj6(lVA=8EI(IY)?D=Lvq&zG92=q3X zJbCo=&C7qCx>#-#fBG9wmj_qdcf}oX6nxqIv#sS;jzzADONiU^8mbnoyy3fpQv7dH z6(R22+tDw*zH`5>bXpmY^tVI*7q{sL6A971xHRr+(m=-%DRL_!{@&%QL;mYU!sFh* zE<9DYtcv7O-M!Z51f{j4A|8-Lh(AMGyCOWZPm5sw4)@9PyJq_5dyj#F+G{Oz0>hF+ zT&5w!cIhmM$5$`q?WEos=sVD89xQRgT)=^f_9t306V}>_?GF!9UpDgUA9aDgU;LeS zGIG`Ak-WQ%KI!vYbwRI~0Aj+6HkZgxFSXPae|CR&H5w;f+H!Jab-T~P*rj{o-((HB zyJh-+y%4eyZCq2cVegIc(a|ZR$$y<@Z1|7C;cZz;Ti`|_>18J_!#{7!iOI};D+}fA z0h{Jx)K+`FpEvaTf~-g)m~$+)HT_%n6S3n%)Qh;_^;2 zrHE&D)|!uev-b??EU3m=UlJA_dMq_l*J=U-iCm!;)Aa}Y;{p4Jj!%DdeDrM)bzTT~ zcWcjBh&ajPav}KD^w)?7{Tq&p?;buSzFH9)^dd)>>oS}gMfinla)%uA^tM^MR(|Xb zJgT;>Jn+I}rId%(RM{B1bt>Yp`>IzaR*~Jk;V(>Ohvz}|nxwq-gk!z+Per7vJAC<@ z%&KS%{1Br!sU#`w(N)h!X6&{*X+_SB!@ms_dku3hC+sNpv(PrIh&oE#>|XTbUdPS& z->HExk33@upn2bt9NE()XWO$R9ADtKlcM^}lk3?H1nD335#L6Z_*P8Rdqn!Z-pF`u zub4d+WhPw4oPKa@X>lP$5Qi(KJ-YKhc=sK9{R+3!7vTX-#lHg(_V{jaObvkolP`&f z#YJ|W=SLNjPub7D=VNaK zs541@eo{-{E-*Tkb9!jo{&sHX@CL-9kKNht7iVltrY%^xsp;^6ZH<2Zn~$#+8A0xW zoYUIEE%%z~T-jAl!iv~6Qv}AV;uV!qJ1m!V%+ZK zCeOVQap5m%{}4;4IPU#Fe%ao9;?*10@wmTE1i#%$lCBx&voF}OYi27O__IlVJwM0pSfbx2sM-`T?opgf02g#cT_!vWK&C%5 zhGJZvi?oz8Nky+#P-I=d&H z<*10nvHj`L&8>we3l~5K`tb=LuunhmGI3LJtrrQY5gCj%mp-npS1zJnoY@4RWXkTK z>Ym*@PMaEQ6wE~IxoSQ&yDYo*x+Zgr!iu;nv zD~jZ=%4aS8Rd~jr^=G|!G|3+OITCSnUc8-t`BoEsl_o4*{fPt0&je%8_$?~>p@Dtk-% zZO)`ug%aF$!u78g%v~|hW}VshO#!v3>swTvoo0dJ%u`pVGx8Zh)A)8)OFtQsnlbTR z-LgdMyr+~C++$64aZ2cWVbRTRUS~uVoLDdMDaAw;`zBSCtc%2#Q0hEux9xm#t>}!J zwW(kFN6#+AHq*lRj`+o!(wo-2JACez^4W$bC4jA!d%IuUc=B60;yY6G398%PJB@3z zQI`T&o_1s(?6do1<(02)H>Xc_^qE4@>++B*mTX+SEO=o|e;uQLjRx}JcTmAf;wyL~ zLJbaM6&mgh=;y5mN=}}kZ@L`A+S&Cbq}z;JqL)s>_r`xFzTE9|ohpR*-t0z z(IdQHM9r9=#gpT>B*qToKG@GO!=T6U*@rhcyvwV;p^aK8hjw$E|Kq^+{JQ(>+IwGb zf}e*thR$Z7%!uF5&;DJuH7D9VVkJ^?;>=?c2AfW z*9UnQ(N^Iu!Ot7++|YZ$_``mKZ{@2TMNwx`mD;`W`n93N3*U|}z#s}NTmEc|{qE2_ z>3>(9pQT~g8^~}Itdl`sp%XuwE9tsSFc{LgicUMJ|RhRQKx{ZT1p0ILrVe#^$tOe5Q+1SNMan$nz>WW60j7R??54}e-dtJG1 zSCH`jGWK%BFR*A2(2SaQErag8f{7>^c*cFUSk4==y+~+K9fd#dr6yLbKT~nH0iZvH zs63qNbosepie%v)yYgd0**06cct10N%3_xkr%eAt*dZc;oE^~S~ev{Ta6ZVRQF zHI18<%Z><(9s>SFn)avjlz*Mr()s2Dn&^>xHD$7of#UP zS4rU+bfF>5{HK2Xha9W_+s_AY{iS%Fu(7wTs`ccBWmjaP-hp>B{S72g$zp)QYku%+LPbJZ^ zt94rj(=@kNfy+Cy8rv!wTemS{tcTxTojQBSbWSwTLI`~~4j99rMow3`;S`^ezy zv*7!qSuOq9sO_T-)h8sw&z?;6*9^3F%s=zsq$6}1o1uvNbLB+(x7VW}7ar{M+ZV4( zv>Hawch|Qit~(ahm$+v8EU^TLrufps0D?mc@0O5PK216M{HVXY1?T#=8!z$vk%_{E z&)N%_?%Yz-g6*uV?I(+`Thk|A?I@EbcF+@Q@K2655<<1Hz~pq-pKL>aa?HgK3}#X* zx&l`I!7RQIF#mVH^#>cLxntiU^!^av?&H2JhNG*&Wa}TYOkNR@<4J2z%r3Vsd0aI4 z3V%2#CF9j5Nq6tik?1B6S7v*7I~{nqm@Jy*}^bhUK6q+Q)qx7St|= z{BrfPGC8Y|?>!KatqJ>k!#5t60&P%CzO2|*%Mh#jq6 zLX=Qi?QQH@Q6ff+UWpka6=Lf`)vmqU(xO$Py2t&tzn_2Mob!C1bDsC>{W|78j$?%g zuabIq3xUUu+p@OV_q3{fs{C(3Ps6cCNy|a7OYZfJR9xQJe(Iu2rp8Gdu)aS~70l@b z3BYNz8SkL+yP8;Glbz2@w~w}`ZlNSNG}at69F3#=hRQd{K7b&<#8pvS>$P-=;o9`HMR-hS4^wLx8o|L%1Q=;c0_ znb~LhW>u+%C91_7KLyNqN5APzBq(z39Sy$tW?WPkfubX*K-FJ;{pll~T zjA-)lij2!Nw3ge_(;sNR>{#$uhAkyk0WjoZFo+uf)(EO6naIR&5|QMG`YnstFG>$n z3tUA83O672+tlUcSZ^89!2?bhMiRV5O|GE*=-m%Y^M?iKO-jGG#g#rR6KBL2D11xnuv4gnwoj@H)Qy3{%f9UGt7avGe5E z$x>xtVX#@f)7HK31*z^38a_hfTef^hr9vU2DSaTo9Uw=isk9dXs-|t^3 zOH$u*j{0tf|NOk^yWnyce8}RO%t*css5knRr>^}xDVG|9C*I{hI5azB*D7)A zFVuZVH85WJwa<~ND{=)Afn$X>+@LT-yLXM7yZC${Qlf|qU;#CZggHSub|xcghWzql z_KwDZ4Df^;#@l!XWS3gYvISzw+Mdd%CL>%25mQc8K`V{5#wAqU+<@w_yeu~m6`7fB z;7mD5Ozq*0G6ZR){DSu|EkIEa$aG+i8%iCnNeII*g2Ce`O|&>|%$QzmSe}(8 zN}W;-MPh3Bs}}%8#uO=MO~ny7ggYLLsdZZN2NWz|B_Nn~ielIp#7GnsHfG{lADUX^ zMCwOjA?Ogy2;D$JdqN&V*D>-j3GuFxuVtufKS|SctT!$KC!^e^XhCF*TYx^Z93_Z> zjS6BqKp|sFn)FaWS%^>2IYz{fy-?T zN2J3vm|@t=;S313Hpp3#ZUjZaMpvf5gIV(d#pNMQu%M8^dC@TE_7U$fZZ(^C() z?yQH#mSP~UJBx!8iPE#=^ppa`E$p&;STL}+9oe22$)dpNa_3HfFYxmC?3jUm<2S3+jP(@hTCChSeF`98 zTasCby^*PU>%pGGDVJWNqoN}?H(U*!At4GB0J+z-WfdG%F+L!zRN6lXX$wwqBsu=c zXBC2~$q)U*fojKRUPmoxIoQtjU)wNMZ){Qr6%gS31<71o{d#%TELB&~ymKB|iz;g; z28}e-|90T~clP?>A)e>PifVo2^}MVJ)fK>Lo3<^9obL^}rm(w;!aAisg8X?iypgHr zljSByrSo<h_xIYQ1(y2y~Ul91iVfcf2x5Bf_}^24@R~J*uBDXc@kCbhkH@? z`|b#+4J8Y1EkvK{8}f|z^w5&3;`ck{)>!Vsfm!_bVBmMd^~5jH!j1l3aX7WW1v%uI zj$3=?XZS^ek|nG^246hocv#D9jdVOucIxKDsLR@V}o8D4{k}E+{|N@*A((pzR&s*r76#!aI3zKv<6>m`_+!)wq3QR9P_{3C^y(stEfJ!M0NH}XrHd)eL9 zOaF8u2+uPM>Q*aQyFMfF=XQuNPvfP>QV!Q9+#(WprtEp_l?8a&zmMCp+yNGbeN<50*+BA2de-8+NO}q*2M^1WYP!UuS!{O`TBBrQ)=nJU*c6~ zK7KY@Z+h_IF3oJ(i1S>@z5Ua(!e4^F&eeW8PTT%v`st6?BszxNTG(zZJ22@fKj5jK zx@PHY^q+^G+o~Qx<7#6EnDBm^;;mcK^dV*^zLk6>*Rn6__k%>l3sKLX75ASbSiv^L zg-`0!bAq$}jXOX<=9x(K2N7+bzMebx$}I4ys(w^?89Xv)Jm7zc(o~r=hg6D+)8;gr zrRi2{4+;6_XJo`0SxddyrJ-3ynJ$xb@U9*$yZFDU(KWAtn8zr{03j965QP0)`E>3z) zU9UX7Q`$aPPSg&VWq;EtC;v^C)O4P|8TETp@C7}RuG=Yh0dbqJLu|ftPcBG2j{la% z+<1un;jaKVcqkwGVJKc)RN3j4>d)kAb!D873FhAUM>|HL-{#lszICb#O?o_ zmfjVLFtt_Tyg-DvzzM-7wC!%`R6+McK?>vJLV`XZT$%JL_U)R9oOWpGwGQR2_*0GZnnp&~dDQl4m%Xd4q_YWi1GOG+F*4qE% z;+gKnNQLuf`#xt6{T+R2OzWle9m{4H%v%7rUFq9Ux?dsLGwFLJ@nPC*h<(?S8voR9;aNqj&lEFm$N**+|5>_RpF3oTHyRJyZN&*3NeeuOnjXl^Ybr z=uS8)-+rfSK(36{v=H)8$R%FK^|`ZDBecQuYKI8FaPgG!=VkSOGh^Mp+O8e%K);#M zQ8PFgbtP0!fo!$f7(X?b&9gW2Tq$h?dq7oW0}>9U7$gDRFCh*>~H?P~TQ`OR&oKJR0lc}dsmr~K!&A+fFv z(r2{MYIAR|uJJPi%NW9I;7PUjSvyjjAvz7{nG7ARREG~S;F+%(+ zTQi?!M9B&^)_aY(KT9}2z0gP*yAf{pIv{R2*s%moGauM_YVLk&S7NGm zTnrPEMAp~_f&Mp++snNZ?%5#Va{XPjNxAV43sjqnK&~7tUCueg!-ml7X!U2K9(^>M zni}=esnSaJAK(?S1Jtl$`x)a4#s#kLgRUZql{vSI-0No1yeSJ8CHXZ)M|%qmYU`z{ zQ_}V8(Ik~puNMi*>o((`|2&rvYj%HcWE;h3@Fv&NN){tIwI=?}QNCF{uJ>dTa{Y1C zb&rQPwTOjX!|BA%(0>m4MH70b4E`ZBM{bQw6W2@D-V~cUuN`)PZxevUUzI*7^H(^? zKUZO>M*PVAm@knn{7e-8sZIl9zWH-NEZ*>6;B>wpV>>SU74G9o?9BtkXF7uF z_u|QW*nDEULQK^ip*elWpLPQ>AEHTuwAJn7nxs8{hK;@s?j0$S`PS`okhFmF)N$qK zr06m&)-s~<%t**^)Mq)JfTbyax6-)N|LW3owpxgnC>#ic^8H3*>5#Q=VQ+5GH!Y{ znS=9L(VKJLN1Ey4<<#x9+8UeL~zeu3+Vt8j)j{UPec$x4@$I%J*(PD!T8Q$(7FOn`;}yIHw{w)L)+lvgD? z&+2%N#Zt3dz63qG{U(?XT6X~|AG}vE%SiCt<8FO{{R4c)9;K!~9eWbQ7t>VDv~`z= z3B(4`Riwn#S54?aa7CA_|6tUp8>a5{9mmHRsxMu(5=y|T$Ah>U$AF~GI943THTIK- zw2HmU5u*`Wd_?vYHADY8t-g&*@9Y5Ch*XcHcK$8&p7(4@-)}6vqSAD4EsO_&Ijz2< zJOj>~R#-@JtGVQU;r#hqZ;F5XOh~HHE!W4_D{|(b^e>C>`#@%_{m#SncbxSMnxE$7 zjH|x#=+E)z!idnIm9wGq2!hBjR|~7)x4{2a~i!tb6 zS2oXtbr@a_q%eM-il?-F3csM}L~}bp-KXT${4W9bz-Q^`ot4_O(oU0q?D1DsM})5m5BavRuv>kG`MAPBIq4bjt5w!5r#b+3 zGM6(VD_o8lImqT zthnllZ67s0|8-}hhOqeLX>q+O_{#nt3rZ~c6^>H67pMJ*hN7={PYx#G1R+6MHZ^MNi-Dd*I}+Ji_PiOIs@;@?=VE2Fd@K zdlzoCGvTY?_(2P6vs>$|mZ{y*txc)o+-_XVj;-HM5y~=fVMNyz9+K5swg$IOl55 zhf}H_N~;56jCM8hckdfq=+}}L)(d;0w-j&o-s}PN+s&7}2RBQ-TzBW=)Rh}go@HpR zlTjw7{-2WL4m;bN`l8&FOw?q`?d=Zs&j&vzva*Ba0#94sRhEoBW0cT99^>_I{nCF3IDSyBHV;_8Wq2B zcQ55F4@cX57W?L+0^7K;OvYD*3R@oTuK9ZX?|*hAUcbo+DF0(KZf=|w6ElIACmS#y|;^<$;-aqJW&*sQlIYx5A|CcU{ zeNwma#75mNLeahe68g0x$WZA*Tg;@b6#3EJQNfytkk<20gW69eS8MfTg(xFp&;1&@ zQHFZ-e{*~}xY}2VfZxCSu14v!nRT52?`0V-wu#6;@w0lon?0VbR++pbeLMk6OFF}h z2_K%9O@zCSpX%_Ut&1E7vVF;aNiNEwgLL1-=ORNXz3Q2Dh6 z@NH&M!-Ak&Wq;chNmTU-Y#=p6P+=M^ccI@JPR~wPBqg^90@y2qD>CIld+NVMx+9T#6j*r=n%uCvzk*&G8rBc^r zmTFEssI<=%&@8K&{0go3;$5r8;tnO|&Ew+;iLs9pX$y8gK1)5wOm%0C-B4jdWs;Oo zv7OdmzCC7u{?&dysPs(a&HI7FZ??izzI@B8uWy~LY#F$Rw@3^JV{nRp7k=F;ddFs% zKD#|P_NCuzDm1J9hwiHJLFSGBWE?Iu6@3YL|6M%n%kvQ!^sFbj???QXxIKz zlDA+tH)od(zoN7=E6%kSb+*uq(3AhJU7uE3PJ)VZGAx_>`-QW5^U2FDXcQ7d^ju7- z9?#oN^<}LtgB7Ih>nr;GgT_2*F)ao_-y!Clb`!f&27LFAZbO!D!ksHuLa=~*Lo9?2jZ!P)cI@HXk?3LWq zvrjoh*|xVV82o-RhNR^hek-D*_zqJJp*V0ogw2{K|6@>~^F;la^ioKJt<()q6C*!8u7)+u&}qr1B2#!h%+2j6sGmCcmh-VzrLHLjH`b7xm!@CpVDG zV=l_8tdJ=qYSvg2ySVsb;e^l}i3%gzN0zXmp1#3`tWs0&Wy+e#2HQvHNpNuDH7N6` z8v&#Pp#tp+as-yW^hg>G{&5O$p5FFhx16jTNNH8b5hbAjGmqX&1np@X_9pmH6+tny zh=rATsH;9g_>iuJ-V67c^t*;k40hA?6Y{esiP81~N%~oNeyCDwOPvgI^AkNr+DNV=w5z{w?D|$- zT&Wz(N3wO0`Pr2*Ha&7We-Wnp4nLKn>zJ?VAl#V*9yy5pfss-#5dVTi>9tMnGv7`}cbk}b z@kkc5rLq^sRo4);KC&{5Ie?syOM!!Es-a!EmbD(z4n-CPwnhzw0F)5mqiD8Q^nP|( zS(ISdL`SiX{oD+)24acO&ZV2rO<9C)_&9|{6IZ*P+UjK{idQr$s(MK9lmzfHjj6vhp7tbrKeKgQA+u@Fp%sZZEx_{(mlD_ z0=xMvGD%o6M7x?OS6PS+{oo%wuigmL9%GAv)lsUp2brnaUe9S>h zAV^f(qHe+$AUMh1=hDj^68eJieI+4olN~tUM3+OUsTZ;0jlz~HauzdbVWUO|l3$PLC)LOMrbr!a2= zQ&8P{t2X#mhFx~H{_q<|jX-7SLH#9)WsB=xg;Yspf)^#>r26IrDxZ4ORh!(4l$Hy( z_QxvL2DZ8G5FlDrqw!R-aASt`b2nsTTyGmmEJDw(EJrxZS$8>lZpH*NOt^H7J>XxC zZyh1P=oMj=wS7ms<>9?G^R zU(%8%MniSTfl9np!BvWiZK={t?{j?mO(Dy{9ln|lrdI-Ol*uS=zp4GsGq8eS06yoA zQQu0WdgZ$otZK5MZFp^`X>3&Sl1*DZyQ0?f$iH8Er5(3U9g{o(+`?2c474lY)$vRO z55l`pLp@?u*-Qx;<{PzO*WdL5>VIuqLNR*J9CsSJ+XRA`Q)n#$q_ zhJbRQiP7nGGWELn7pgQLO`GY*ZOQ(CB4xE+4!M3j(R+gd-DfvZC)<#9U@yzQzMVeL z-R2DA5x8EJ1}h}!U?aU;SyWL+tidN~c&CW!GMSu2E9mCJ2Nn zZ%+r}(nI_;E3u#uDZDpAyO|$bTJ_A9#fnQujJn7$w0(!Y%St6@O`6&@u3QNn?8_x1 zBb20t@$tFe^N-EbnZ{W=HW|aVVj(%7_G|bc3UZDE6)C0HuDzI7(%fZF(F_TpWyRAt zoR6NrRD0C$Qz}M-LVB;*-gg*Xq*HEw(&)(v)j&mKnYQ@#S<>ges%uku>Uq1#ZTX{H z2!4KoN#MAAgvs6J#D3_J@i-LE%L-RFX z6tjH~HrE_1W<5a|%sYEIvCyo7pgB0#wLjuXNTyA!TG*tWN8mJa#33kNq*5o{T5*X~ zj)B#eW!kdXCq?(Ut#}xI*}#!%W5(~ym`R0H$>rrm(~76)J`jnTc5-)wOW&UTJcQ2! zVvrK%G1WOGtFjSAn+RI4pUuEf^o0S5(S9Y{1U>v< zx~!@H6~sQr*(j0>37d|_Z?r^es;S4D9I7O2P+`ymOIK9Kogn#y7!9dvNfkg~qSa@P zrPTIBK^0d`jT<->918O;h)UhWGkGPHjQNr6JC6s!iV52DChqd^_}v>XPiHULOsiC~ z>a-V?T!!h=w%NmFc&XGKp0Nxq4@=2w1#5;q?nd&FL1Y^cTGR_xo{RS8dN0PhROwEX zms$d99TGTh8yh=o)I#PM-Hv@UvWHid^;I@7bCBAcVFu>vX#2W_q8xHt;YwKI^hza2 ztoMkcR=83G0->hnP7Jwo2g|@7nqxWtRCvtrVxv(cuX7Fzs#$~(<@XJ@##Ebc>>*th z%E+sAlo~vnK%wUBu&45(%R0IV?01&ft^-5l6yAB2iH4d`b^7{A%Nh_}xiETB$+hJx zP95cA272W^z3Z5zkVvC&6Z%|F1ybom?anTyc(3K7VW}?Q;rD5f>X5-L881|YwTqU7 zB3`wA))s^GW(thB#-+p-0`R&huOdja26?5Rh;=MydjmYD3aT1?mJk zH^`o9ZtL`2TMZN$v_vSe&4$+mqN**_<3vUSrGr`6XPOj~@jz)z5f_`=EK1e_sRHD( zpKB@IA>vn76M=;2{qziG)odgkEwf%yL)h);*JRV?mUMOBMkZEpD@aeU0ZTD3RcDEe z5!XhU;k`9LN0nGbWXV{D@l;Jpt7g22yv%9-1IPRL6wYh3rf-i($BDTv-R!h3Kks6D zehx;5Kg(8BwO$#drbc)|wg~Z`U{`bv9_MTw2o?9ZfB)HK?k?OM?xT^>*z38u9;ROtEA@+Bbz-5aAvGjQ5QWXOP)-{ zuPkZT_p{xh_P(^$8dH;5!cihTgevXGpObYs3bs_!Oy=AA#kzG0RukgK!TxZ(1R}M16BlP+b>c?HhQ;=>fVHfW z%zAD)ha4{44?9q_@sfJuh$g3C+Wt{F48@$bB0~wNJoV#8e!<%4nFw! z3xz(HzQ)~+4!6cJ9Ed4TK&ms@AD)oc zdkwBZFA5{j+kFxpUI!H zu0WXytOwX>t4o_Sw=cWn>gIYpYu6P(Iv!K62g+@qq!D)F-vVqvIf1QQh&~}xBazLeAV!OI`XR5v^zcDjLHc2__pE($h3uuAkHH?-=lr}`Cb}#%v$>?1 z8`m}4r2~i}xQ%tuHKMTG7YXdpWp|Ty%o>|C&lCcBsF$9IfNgrYdVJo zM{Gnz#;kjj*LF>2apkrKFH#c{Y%7BRHzZz&IryPrltOTAHyYj@>aVNFT-jJJCQ%ZI znqB^8#)qX5OSUe2dNZ2^%g~(AE@!Tv7xZa;x$&XoV;YYtC<;O|&|KN++Uu~fU%=+i}8dH{*T5os%y7ew+gVzW`A#HJat zc0Y8sy0celjyP_zyVlET2;;P>U$!dgkaCr5RuTL;y&v5sHI;yl^Q%s%u>Q{Zfr zt6#9MOOcbWZnXW{4vyH0jKeQ2!%3W=d}8N(u}iGS8&bRP$4I(H$=Ysc7%@7U!0g25 z_EVT`6~ws(xswxJc=BIBSQnf;w^rn-L)utdhO;A!r@Eo==5ls;XD*gYY;4Vq!Vzk` zyJkIpXtas6)Js?>fpa6{eAz_idgvTa_LEd=iLtbkIn}oeM>fGbua7MF#rbx_ zr@Tzy1U9iXPEm)b;RosBwU#gwc^t6)L{;!DX_1X>g8S~Sb;E-r72FK$8hMKWxB`G9 z5(!>e*W*nfgL!MB_%}zY(v+8)c9+mi-8oGkiNpaSb7{7-Gng3c-PKC*)UmM?6p_e_ zOCEfq4p-iW*TEkY?mr=h2+y%a8J%K}@-@5}1t|+$*p=Q%HujMU`6<5C-IyhEZ4#knUzb8bN%Ez(>-yR)tpL+(9Og!s zgi!YPz?DL$<=ZxMRG4T$g62}Ipr*e!Dx>$2N-jFyH@{=lqIi}Od?~Wf*K6Mds%)Y& zF*$yk{$*l+|5sp2TF7I4*U)Rl*9ewPhDtaI8)ddwxi{Th_? z#Oe;t=4{TgT!Fb>lBT8^!P=EB9 z`b=X`vI1IF^^Nt(|7KvMW|27gusH4F%WfNw`H#>%xPoz=Nat6yhA>FDZ8F=TdCK}e;v<6H=AHY-%vO||CabNB0_1KEBR|K-l*@MtxLG`L5+5T;MTjY+ z>-^56BsfbHNp^Mab#)t#Vo4)?x@vj)Ncd0bWoyS&V6{*BAG3ZcWH3FgK!tqj{{eH- By=(vg delta 28885 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∋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 diff --git a/man/count.Rd b/man/count.Rd index 38507440..89091806 100644 --- a/man/count.Rd +++ b/man/count.Rd @@ -7,6 +7,8 @@ \alias{count_I} \alias{count_SI} \alias{count_S} +\alias{count_all} +\alias{n_rsi} \alias{count_df} \title{Count isolates} \source{ @@ -23,11 +25,15 @@ count_SI(...) count_S(...) +count_all(...) + +n_rsi(...) + count_df(data, translate_ab = getOption("get_antibiotic_names", "official")) } \arguments{ -\item{...}{one or more vectors (or columns) with antibiotic interpretations. They will be transformed internally with \code{\link{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.} +\item{...}{one or more vectors (or columns) with antibiotic interpretations. They will be transformed internally with \code{\link{as.rsi}} if needed.} \item{data}{a \code{data.frame} containing columns with class \code{rsi} (see \code{\link{as.rsi}})} @@ -42,10 +48,10 @@ These functions can be used to count resistant/susceptible microbial isolates. A \code{count_R} and \code{count_IR} can be used to count resistant isolates, \code{count_S} and \code{count_SI} can be used to count susceptible isolates.\cr } \details{ -\strong{Remember that you should filter your table to let it contain only first isolates!} Use \code{\link{first_isolate}} to determine them in your data set. - These functions are meant to count isolates. Use the \code{\link{portion}_*} functions to calculate microbial resistance. +\code{n_rsi} is an alias of \code{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 \code{\link{n_distinct}}. Their function is equal to \code{count_S(...) + count_IR(...)}. + \code{count_df} takes any variable from \code{data} that has an \code{"rsi"} class (created with \code{\link{as.rsi}}) and counts the amounts of R, I and S. The resulting \emph{tidy data} (see Source) \code{data.frame} will have three rows (S/I/R) and a column for each variable with class \code{"rsi"}. } \examples{ @@ -60,6 +66,10 @@ count_IR(septic_patients$amox) count_S(septic_patients$amox) count_SI(septic_patients$amox) +# Count all available isolates +count_all(septic_patients$amox) +n_rsi(septic_patients$amox) + # Since n_rsi counts available isolates, you can # calculate back to count e.g. non-susceptible isolates. # This results in the same: @@ -69,24 +79,25 @@ portion_IR(septic_patients$amox) * n_rsi(septic_patients$amox) library(dplyr) septic_patients \%>\% group_by(hospital_id) \%>\% - summarise(R = count_R(cipr), - I = count_I(cipr), - S = count_S(cipr), - n = n_rsi(cipr), # the actual total; sum of all three - total = n()) # NOT the amount of tested isolates! + summarise(R = count_R(cipr), + I = count_I(cipr), + S = count_S(cipr), + n1 = count_all(cipr), # the actual total; sum of all three + n2 = n_rsi(cipr), # same - analogous to n_distinct + total = n()) # NOT the amount of tested isolates! # Count co-resistance between amoxicillin/clav acid and gentamicin, # so we can see that combination therapy does a lot more than mono therapy. # Please mind that `portion_S` calculates percentages right away instead. -count_S(septic_patients$amcl) # S = 1056 (67.3\%) -n_rsi(septic_patients$amcl) # n = 1570 +count_S(septic_patients$amcl) # S = 1057 (67.1\%) +count_all(septic_patients$amcl) # n = 1576 -count_S(septic_patients$gent) # S = 1363 (74.0\%) -n_rsi(septic_patients$gent) # n = 1842 +count_S(septic_patients$gent) # S = 1372 (74.0\%) +count_all(septic_patients$gent) # n = 1855 with(septic_patients, - count_S(amcl, gent)) # S = 1385 (92.1\%) -with(septic_patients, # n = 1504 + count_S(amcl, gent)) # S = 1396 (92.0\%) +with(septic_patients, # n = 1517 n_rsi(amcl, gent)) # Get portions S/I/R immediately of all rsi columns @@ -102,8 +113,7 @@ septic_patients \%>\% } \seealso{ -\code{\link{portion}_*} to calculate microbial resistance and susceptibility.\cr -\code{\link{n_rsi}} to count all cases where antimicrobial results are available. +\code{\link{portion}_*} to calculate microbial resistance and susceptibility. } \keyword{antibiotics} \keyword{isolate} diff --git a/man/ggplot_rsi.Rd b/man/ggplot_rsi.Rd index d5d9c286..9dc03650 100644 --- a/man/ggplot_rsi.Rd +++ b/man/ggplot_rsi.Rd @@ -68,7 +68,7 @@ At default, the names of antibiotics will be shown on the plots using \code{\lin \code{scale_y_percent} transforms the y axis to a 0 to 100\% range using \code{\link[ggplot2]{scale_continuous}}. -\code{scale_rsi_colours} sets colours to the bars: green for S, yellow for I and red for R, using \code{\link[ggplot2]{scale_colour_brewer}}. +\code{scale_rsi_colours} sets colours to the bars: green for S, yellow for I and red for R, using \code{\link[ggplot2]{scale_brewer}}. \code{theme_rsi} is a \code{ggplot \link[ggplot2]{theme}} with minimal distraction. diff --git a/man/join.Rd b/man/join.Rd index 32eedc22..b8a1979c 100755 --- a/man/join.Rd +++ b/man/join.Rd @@ -11,22 +11,22 @@ \alias{anti_join_microorganisms} \title{Join a table with \code{microorganisms}} \usage{ -inner_join_microorganisms(x, by = "mo", suffix = c("2", ""), ...) +inner_join_microorganisms(x, by = NULL, suffix = c("2", ""), ...) -left_join_microorganisms(x, by = "mo", suffix = c("2", ""), ...) +left_join_microorganisms(x, by = NULL, suffix = c("2", ""), ...) -right_join_microorganisms(x, by = "mo", suffix = c("2", ""), ...) +right_join_microorganisms(x, by = NULL, suffix = c("2", ""), ...) -full_join_microorganisms(x, by = "mo", suffix = c("2", ""), ...) +full_join_microorganisms(x, by = NULL, suffix = c("2", ""), ...) -semi_join_microorganisms(x, by = "mo", ...) +semi_join_microorganisms(x, by = NULL, ...) -anti_join_microorganisms(x, by = "mo", ...) +anti_join_microorganisms(x, by = NULL, ...) } \arguments{ -\item{x}{existing table to join, also supports character vectors} +\item{x}{existing table to join, or character vector} -\item{by}{a variable to join by - could be a column name of \code{x} with values that exist in \code{microorganisms$mo} (like \code{by = "bacteria_id"}), or another column in \code{\link{microorganisms}} (but then it should be named, like \code{by = c("my_genus_species" = "fullname")})} +\item{by}{a variable to join by - if left empty will search for a column with class \code{mo} (created with \code{\link{as.mo}}) or will be \code{"mo"} if that column name exists in \code{x}, could otherwise be a column name of \code{x} with values that exist in \code{microorganisms$mo} (like \code{by = "bacteria_id"}), or another column in \code{\link{microorganisms}} (but then it should be named, like \code{by = c("my_genus_species" = "fullname")})} \item{suffix}{if there are non-joined duplicate variables in \code{x} and \code{y}, these suffixes will be added to the output to disambiguate them. Should be a character vector of length 2.} @@ -36,10 +36,11 @@ anti_join_microorganisms(x, by = "mo", ...) Join the dataset \code{\link{microorganisms}} easily to an existing table or character vector. } \details{ -As opposed to the \code{\link[dplyr]{join}} functions of \code{dplyr}, characters vectors are supported and at default existing columns will get a suffix \code{"2"} and the newly joined columns will not get a suffix. See \code{\link[dplyr]{join}} for more information. +\strong{Note:} As opposed to the \code{\link[dplyr]{join}} functions of \code{dplyr}, characters vectors are supported and at default existing columns will get a suffix \code{"2"} and the newly joined columns will not get a suffix. See \code{\link[dplyr]{join}} for more information. } \examples{ -left_join_microorganisms("STAAUR") +left_join_microorganisms(as.mo("K. pneumoniae")) +left_join_microorganisms("B_KLBSL_PNE") library(dplyr) septic_patients \%>\% left_join_microorganisms() @@ -47,10 +48,10 @@ septic_patients \%>\% left_join_microorganisms() df <- data.frame(date = seq(from = as.Date("2018-01-01"), to = as.Date("2018-01-07"), by = 1), - bacteria_id = c("STAAUR", "STAAUR", "STAAUR", "STAAUR", - "ESCCOL", "ESCCOL", "ESCCOL"), + bacteria = as.mo(c("S. aureus", "MRSA", "MSSA", "STAAUR", + "E. coli", "E. coli", "E. coli")), stringsAsFactors = FALSE) colnames(df) -df2 <- left_join_microorganisms(df, "bacteria_id") -colnames(df2) +df_joined <- left_join_microorganisms(df, "bacteria") +colnames(df_joined) } diff --git a/man/n_rsi.Rd b/man/n_rsi.Rd deleted file mode 100644 index ab5fc099..00000000 --- a/man/n_rsi.Rd +++ /dev/null @@ -1,30 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/n_rsi.R -\name{n_rsi} -\alias{n_rsi} -\title{Count cases with antimicrobial results} -\usage{ -n_rsi(...) -} -\arguments{ -\item{...}{one or more vectors (or columns) with antibiotic interpretations. They will be transformed internally with \code{\link{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.} -} -\description{ -This counts all cases where antimicrobial interpretations are available. The way it can be used is equal to \code{\link{n_distinct}}. Its function is equal to \code{count_S(...) + count_IR(...)}. -} -\examples{ -library(dplyr) - -septic_patients \%>\% - group_by(hospital_id) \%>\% - summarise(cipro_p = portion_S(cipr, as_percent = TRUE), - cipro_n = n_rsi(cipr), - genta_p = portion_S(gent, as_percent = TRUE), - genta_n = n_rsi(gent), - combination_p = portion_S(cipr, gent, as_percent = TRUE), - combination_n = n_rsi(cipr, gent)) -} -\seealso{ -\code{\link[AMR]{count}_*} to count resistant and susceptibile isolates per interpretation type.\cr -\code{\link{portion}_*} to calculate microbial resistance and susceptibility. -} diff --git a/man/portion.Rd b/man/portion.Rd index a2cb59cd..a5420e64 100644 --- a/man/portion.Rd +++ b/man/portion.Rd @@ -31,7 +31,7 @@ portion_df(data, translate_ab = getOption("get_antibiotic_names", \arguments{ \item{...}{one or more vectors (or columns) with antibiotic interpretations. They will be transformed internally with \code{\link{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.} -\item{minimum}{minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA}. The default number of \code{30} isolates is advised by the CLSI as best practice, see Source.} +\item{minimum}{minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA} with a warning. The default number of \code{30} isolates is advised by the Clinical and Laboratory Standards Institute (CLSI) as best practice, see Source.} \item{as_percent}{logical to indicate whether the output must be returned as a hundred fold with \% sign (a character). A value of \code{0.123456} will then be returned as \code{"12.3\%"}.} @@ -104,24 +104,24 @@ septic_patients \%>\% # Calculate co-resistance between amoxicillin/clav acid and gentamicin, # so we can see that combination therapy does a lot more than mono therapy: -septic_patients \%>\% portion_S(amcl) # S = 67.3\% -septic_patients \%>\% n_rsi(amcl) # n = 1570 +septic_patients \%>\% portion_S(amcl) # S = 67.1\% +septic_patients \%>\% count_all(amcl) # n = 1576 septic_patients \%>\% portion_S(gent) # S = 74.0\% -septic_patients \%>\% n_rsi(gent) # n = 1842 +septic_patients \%>\% count_all(gent) # n = 1855 -septic_patients \%>\% portion_S(amcl, gent) # S = 92.1\% -septic_patients \%>\% n_rsi(amcl, gent) # n = 1504 +septic_patients \%>\% portion_S(amcl, gent) # S = 92.0\% +septic_patients \%>\% count_all(amcl, gent) # n = 1517 septic_patients \%>\% group_by(hospital_id) \%>\% summarise(cipro_p = portion_S(cipr, as_percent = TRUE), - cipro_n = n_rsi(cipr), + cipro_n = count_all(cipr), genta_p = portion_S(gent, as_percent = TRUE), - genta_n = n_rsi(gent), + genta_n = count_all(gent), combination_p = portion_S(cipr, gent, as_percent = TRUE), - combination_n = n_rsi(cipr, gent)) + combination_n = count_all(cipr, gent)) # Get portions S/I/R immediately of all rsi columns septic_patients \%>\% @@ -142,12 +142,11 @@ my_table \%>\% filter(first_isolate == TRUE, genus == "Helicobacter") \%>\% summarise(p = portion_S(amox, metr), # amoxicillin with metronidazole - n = n_rsi(amox, metr)) + n = count_all(amox, metr)) } } \seealso{ -\code{\link[AMR]{count}_*} to count resistant and susceptibile isolates.\cr -\code{\link{n_rsi}} to count all cases where antimicrobial results are available. +\code{\link[AMR]{count}_*} to count resistant and susceptibile isolates. } \keyword{antibiotics} \keyword{isolate} diff --git a/man/rsi.Rd b/man/rsi.Rd index d925892b..404842a3 100644 --- a/man/rsi.Rd +++ b/man/rsi.Rd @@ -12,7 +12,7 @@ rsi(ab1, ab2 = NULL, interpretation = "IR", minimum = 30, \item{interpretation}{antimicrobial interpretation to check for} -\item{minimum}{minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA}. The default number of \code{30} isolates is advised by the CLSI as best practice, see Source.} +\item{minimum}{minimal amount of available isolates. Any number lower than \code{minimum} will return \code{NA} with a warning. The default number of \code{30} isolates is advised by the Clinical and Laboratory Standards Institute (CLSI) as best practice, see Source.} \item{as_percent}{logical to indicate whether the output must be returned as a hundred fold with \% sign (a character). A value of \code{0.123456} will then be returned as \code{"12.3\%"}.} diff --git a/tests/testthat/test-atc.R b/tests/testthat/test-atc.R index 342aed7f..fe6f3de4 100755 --- a/tests/testthat/test-atc.R +++ b/tests/testthat/test-atc.R @@ -10,8 +10,8 @@ test_that("atc_property works", { expect_equal(atc_property("J01CA04", property = "DDD"), atc_ddd("J01CA04")) - expect_identical(atc_property("J01CA04", property = "Groups"), - atc_groups("J01CA04")) + # expect_identical(atc_property("J01CA04", property = "Groups"), + # atc_groups("J01CA04")) expect_warning(atc_property("ABCDEFG", property = "DDD")) diff --git a/tests/testthat/test-count.R b/tests/testthat/test-count.R index 099baa15..cb08de25 100644 --- a/tests/testthat/test-count.R +++ b/tests/testthat/test-count.R @@ -10,8 +10,13 @@ test_that("counts work", { expect_equal(count_S(septic_patients$amox) + count_I(septic_patients$amox), count_SI(septic_patients$amox)) + library(dplyr) expect_equal(septic_patients %>% count_S(amcl), 1057) expect_equal(septic_patients %>% count_S(amcl, gent), 1396) + expect_equal(septic_patients %>% count_all(amcl, gent), 1517) + expect_identical(septic_patients %>% count_all(amcl, gent), + septic_patients %>% count_S(amcl, gent) + + septic_patients %>% count_IR(amcl, gent)) # count of cases expect_equal(septic_patients %>% diff --git a/tests/testthat/test-freq.R b/tests/testthat/test-freq.R index 4940fb54..5393cf97 100755 --- a/tests/testthat/test-freq.R +++ b/tests/testthat/test-freq.R @@ -43,6 +43,11 @@ test_that("frequency table works", { # list expect_output(print(freq(list(age = septic_patients$age)))) expect_output(print(freq(list(age = septic_patients$age, gender = septic_patients$gender)))) + # difftime + expect_output(suppressWarnings(print( + freq(difftime(Sys.time(), + Sys.time() - runif(5, min = 0, max = 60 * 60 * 24), + units = "hours"))))) library(dplyr) expect_output(septic_patients %>% select(1:2) %>% freq() %>% print()) @@ -119,7 +124,7 @@ test_that("frequency table works", { )) expect_output(print( diff(freq(septic_patients$age), - freq(septic_patients$age)) # same + freq(septic_patients$age)) # "No differences found." )) expect_error(print( diff(freq(septic_patients$amcl), diff --git a/tests/testthat/test-portion.R b/tests/testthat/test-portion.R index a86c4640..87bdaa82 100755 --- a/tests/testthat/test-portion.R +++ b/tests/testthat/test-portion.R @@ -68,11 +68,11 @@ test_that("portions works", { expect_error(portion_S("test", as_percent = "test")) # check too low amount of isolates - expect_identical(portion_R(septic_patients$amox, minimum = nrow(septic_patients) + 1), + expect_identical(suppressWarnings(portion_R(septic_patients$amox, minimum = nrow(septic_patients) + 1)), NA) - expect_identical(portion_I(septic_patients$amox, minimum = nrow(septic_patients) + 1), + expect_identical(suppressWarnings(portion_I(septic_patients$amox, minimum = nrow(septic_patients) + 1)), NA) - expect_identical(portion_S(septic_patients$amox, minimum = nrow(septic_patients) + 1), + expect_identical(suppressWarnings(portion_S(septic_patients$amox, minimum = nrow(septic_patients) + 1)), NA) # warning for speed loss