From ce2cdb930941df43a3c5ae063fa1413432eba3bc Mon Sep 17 00:00:00 2001 From: "Matthijs S. Berends" Date: Sun, 12 Aug 2018 22:34:03 +0200 Subject: [PATCH] support groups for portion_df, update README --- NAMESPACE | 4 +- R/data.R | 4 +- R/first_isolate.R | 2 +- R/ggplot_rsi.R | 29 ++++-- R/portion.R | 55 ++++++++--- README.md | 163 +++++++++++++++++++------------ man/figures/rsi_example4.png | Bin 0 -> 21185 bytes man/first_isolate.Rd | 2 +- man/ggplot_rsi.Rd | 24 +++-- man/portion.Rd | 19 +++- man/septic_patients.Rd | 4 +- tests/testthat/test-ggplot_rsi.R | 9 ++ 12 files changed, 215 insertions(+), 100 deletions(-) create mode 100644 man/figures/rsi_example4.png diff --git a/NAMESPACE b/NAMESPACE index 93f122d9..7ca07bdf 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -120,12 +120,14 @@ importFrom(dplyr,arrange) importFrom(dplyr,arrange_at) importFrom(dplyr,as_tibble) importFrom(dplyr,between) -importFrom(dplyr,bind_cols) +importFrom(dplyr,bind_rows) importFrom(dplyr,case_when) importFrom(dplyr,desc) +importFrom(dplyr,everything) importFrom(dplyr,filter) importFrom(dplyr,group_by) importFrom(dplyr,group_by_at) +importFrom(dplyr,group_vars) importFrom(dplyr,if_else) importFrom(dplyr,lag) importFrom(dplyr,left_join) diff --git a/R/data.R b/R/data.R index f73f6377..bf0c763d 100755 --- a/R/data.R +++ b/R/data.R @@ -279,11 +279,11 @@ #' Dataset with 2000 blood culture isolates of septic patients #' -#' An anonymised dataset containing 2000 microbial blood culture isolates with their antibiogram of septic patients found in 5 different hospitals in the Netherlands, between 2001 and 2017. This data.frame can be used to practice AMR analysis. For examples, press F1. +#' An anonymised dataset containing 2000 microbial blood culture isolates with their full antibiograms found in septic patients in 4 different hospitals in the Netherlands, between 2001 and 2017. It is true, genuine data. This \code{data.frame} can be used to practice AMR analysis. For examples, press F1. #' @format A data.frame with 2000 observations and 49 variables: #' \describe{ #' \item{\code{date}}{date of receipt at the laboratory} -#' \item{\code{hospital_id}}{ID of the hospital} +#' \item{\code{hospital_id}}{ID of the hospital, from A to D} #' \item{\code{ward_icu}}{logical to determine if ward is an intensive care unit} #' \item{\code{ward_clinical}}{logical to determine if ward is a regular clinical ward} #' \item{\code{ward_outpatient}}{logical to determine if ward is an outpatient clinic} diff --git a/R/first_isolate.R b/R/first_isolate.R index 02bf5ec7..268ad604 100755 --- a/R/first_isolate.R +++ b/R/first_isolate.R @@ -55,7 +55,7 @@ #' @return A vector to add to table, see Examples. #' @source Methodology of this function is based on: \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/}. #' @examples -#' # septic_patients is a dataset available in the AMR package. It is true data. +#' # septic_patients is a dataset available in the AMR package. It is true, genuine data. #' ?septic_patients #' #' library(dplyr) diff --git a/R/ggplot_rsi.R b/R/ggplot_rsi.R index 00cf1e4d..190bf601 100644 --- a/R/ggplot_rsi.R +++ b/R/ggplot_rsi.R @@ -21,8 +21,9 @@ #' Use these functions to create bar plots for antimicrobial resistance analysis. All functions rely on internal \code{\link[ggplot2]{ggplot}} functions. #' @param data a \code{data.frame} with column(s) of class \code{"rsi"} (see \code{\link{as.rsi}}) #' @param position position adjustment of bars, either \code{"stack"} (default) or \code{"dodge"} -#' @param x parameter to show on x axis, either \code{"Antibiotic"} (default) or \code{"Interpretation"} -#' @param facet parameter to split plots by, either \code{"Interpretation"} (default) or \code{"Antibiotic"} +#' @param x variable to show on x axis, either \code{"Antibiotic"} (default) or \code{"Interpretation"} +#' @param fill variable to categorise using the plots legend +#' @param facet variable to split plots by, either \code{"Interpretation"} (default) or \code{"Antibiotic"} #' @details At default, the names of antibiotics will be shown on the plots using \code{\link{abname}}. This can be set with the option \code{get_antibiotic_names} (a logical value), so change it e.g. to \code{FALSE} with \code{options(get_antibiotic_names = FALSE)}. #' #' \strong{The functions}\cr @@ -64,8 +65,18 @@ #' septic_patients %>% #' select(amox, nitr, fosf, trim, cipr) %>% #' ggplot_rsi(x = "Interpretation", facet = "Antibiotic") +#' +#' # it also supports groups (don't forget to use facet on the group): +#' septic_patients %>% +#' select(hospital_id, amox, cipr) %>% +#' group_by(hospital_id) %>% +#' ggplot_rsi() + +#' facet_grid("hospital_id") + +#' labs(title = "AMR of Amoxicillin And Ciprofloxacine Per Hospital") ggplot_rsi <- function(data, + position = "stack", x = "Antibiotic", + fill = "Interpretation", facet = NULL) { if (!"ggplot2" %in% rownames(installed.packages())) { @@ -73,11 +84,15 @@ ggplot_rsi <- function(data, } p <- ggplot2::ggplot(data = data) + - geom_rsi(x = x) + + geom_rsi(position = position, x = x, fill = fill) + scale_y_percent() + - scale_rsi_colours() + theme_rsi() + if (fill == "Interpretation") { + # set RSI colours + p <- p + scale_rsi_colours() + } + if (!is.null(facet)) { p <- p + facet_rsi(facet = facet) } @@ -87,7 +102,7 @@ ggplot_rsi <- function(data, #' @rdname ggplot_rsi #' @export -geom_rsi <- function(position = "stack", x = c("Antibiotic", "Interpretation")) { +geom_rsi <- function(position = "stack", x = c("Antibiotic", "Interpretation"), fill = "Interpretation") { x <- x[1] if (!x %in% c("Antibiotic", "Interpretation")) { @@ -95,8 +110,8 @@ geom_rsi <- function(position = "stack", x = c("Antibiotic", "Interpretation")) } ggplot2::layer(geom = "bar", stat = "identity", position = position, - mapping = ggplot2::aes_string(x = x, y = "Percentage", fill = "Interpretation"), - data = AMR::portion_df, params = list()) + mapping = ggplot2::aes_string(x = x, y = "Percentage", fill = fill), + data = AMR::portion_df, params = list()) } diff --git a/R/portion.R b/R/portion.R index 71ed9d9c..d60c918d 100755 --- a/R/portion.R +++ b/R/portion.R @@ -29,7 +29,7 @@ #' @param translate a logical value to indicate whether antibiotic abbreviations should be translated with \code{\link{abname}} #' @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. #' -#' \code{portion_df} takes any variable from \code{data} that has an \code{"rsi"} class (created with \code{\link{as.rsi}}) and calculates the portions R, I and S. The resulting \code{data.frame} will have three rows (for R/I/S) and a column for each variable with class \code{"rsi"}. +#' \code{portion_df} takes any variable from \code{data} that has an \code{"rsi"} class (created with \code{\link{as.rsi}}) and calculates the portions 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"}. #' #' The old \code{\link{rsi}} function is still available for backwards compatibility but is deprecated. #' \if{html}{ @@ -45,6 +45,8 @@ #' \out{
}\figure{combi_therapy_3.png}\out{
} #' } #' @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{n_rsi}} to count cases with antimicrobial results. #' @keywords resistance susceptibility rsi_df rsi antibiotics isolate isolates #' @return Double or, when \code{as_percent = TRUE}, a character. @@ -52,6 +54,9 @@ #' @name portion #' @export #' @examples +#' # septic_patients is a data set available in the AMR package. It is true, genuine data. +#' ?septic_patients +#' #' # Calculate resistance #' portion_R(septic_patients$amox) #' portion_IR(septic_patients$amox) @@ -100,6 +105,18 @@ #' combination_p = portion_S(cipr, gent, as_percent = TRUE), #' combination_n = n_rsi(cipr, gent)) #' +#' # Get portions S/I/R immediately of all rsi columns +#' septic_patients %>% +#' select(amox, cipr) %>% +#' portion_df(translate = FALSE) +#' +#' # It also supports grouping variables +#' septic_patients %>% +#' select(hospital_id, amox, cipr) %>% +#' group_by(hospital_id) %>% +#' portion_df(translate = FALSE) +#' +#' #' \dontrun{ #' #' # calculate current empiric combination therapy of Helicobacter gastritis: @@ -177,25 +194,33 @@ portion_S <- function(ab1, } #' @rdname portion -#' @importFrom dplyr bind_cols summarise_if mutate +#' @importFrom dplyr bind_rows summarise_if mutate group_vars select everything #' @export portion_df <- function(data, translate = getOption("get_antibiotic_names", TRUE)) { - resS <- bind_cols(data.frame(Interpretation = "S", stringsAsFactors = FALSE), - summarise_if(.tbl = data, - .predicate = is.rsi, - .funs = portion_S)) - resI <- bind_cols(data.frame(Interpretation = "I", stringsAsFactors = FALSE), - summarise_if(.tbl = data, - .predicate = is.rsi, - .funs = portion_I)) - resR <- bind_cols(data.frame(Interpretation = "R", stringsAsFactors = FALSE), - summarise_if(.tbl = data, - .predicate = is.rsi, - .funs = portion_R)) + + resS <- summarise_if(.tbl = data, + .predicate = is.rsi, + .funs = portion_S) %>% + mutate(Interpretation = "S") %>% + select(Interpretation, everything()) + + resI <- summarise_if(.tbl = data, + .predicate = is.rsi, + .funs = portion_I) %>% + mutate(Interpretation = "I") %>% + select(Interpretation, everything()) + + resR <- summarise_if(.tbl = data, + .predicate = is.rsi, + .funs = portion_R) %>% + mutate(Interpretation = "R") %>% + select(Interpretation, everything()) + + data.groups <- group_vars(data) res <- bind_rows(resS, resI, resR) %>% mutate(Interpretation = factor(Interpretation, levels = c("R", "I", "S"), ordered = TRUE)) %>% - tidyr::gather(Antibiotic, Percentage, -Interpretation) + tidyr::gather(Antibiotic, Percentage, -Interpretation, -data.groups) if (translate == TRUE) { res <- res %>% mutate(Antibiotic = abname(Antibiotic, from = "guess", to = "official")) } diff --git a/README.md b/README.md index 3bbdcace..e4342034 100755 --- a/README.md +++ b/README.md @@ -24,6 +24,19 @@ Erwin E.A. Hassing2, +## Contents +* [Why this package?](#why-this-package) +* [How to get it?](#how-to-get-it) + * [Install from CRAN](#install-from-cran) + * [Install from GitHub](#install-from-github) +* [How to use it?](#how-to-use-it) + * [New classes](#new-classes) + * [Overwrite/force resistance based on EUCAST rules](#overwriteforce-resistance-based-on-eucast-rules) + * [Other (microbial) epidemiological functions](#other-microbial-epidemiological-functions) + * [Frequency tables](#frequency-tables) + * [Data sets included in package](#data-sets-included-in-package) +* [Copyright](#copyright) + ## Why this package? This R package was intended to make microbial epidemiology easier. Most functions contain extensive help pages to get started. @@ -50,12 +63,12 @@ And it contains: With the `MDRO` function (abbreviation of Multi Drug Resistant Organisms), you can check your isolates for exceptional resistance with country-specific guidelines or EUCAST rules. Currently guidelines for Germany and the Netherlands are supported. Please suggest addition of your own country here: [https://github.com/msberends/AMR/issues/new](https://github.com/msberends/AMR/issues/new?title=New%20guideline%20for%20MDRO&body=%3C--%20Please%20add%20your%20country%20code,%20guideline%20name,%20version%20and%20source%20below%20and%20remove%20this%20line--%3E). -#### Read all changes and new functions in [NEWS.md](NEWS.md). +**Read all changes and new functions in [NEWS.md](NEWS.md).** ## How to get it? This package [is published on CRAN](http://cran.r-project.org/package=AMR), the official R network. -### Install from CRAN (recommended) +### Install from CRAN [![CRAN_Badge](https://img.shields.io/cran/v/AMR.svg?label=CRAN&colorB=3679BC)](http://cran.r-project.org/package=AMR) [![CRAN_Downloads](https://cranlogs.r-pkg.org/badges/grand-total/AMR)](http://cran.r-project.org/package=AMR) (Note: Downloads measured only by [cran.rstudio.com](https://cran.rstudio.com/package=AMR), this excludes e.g. the official [cran.r-project.org](https://cran.r-project.org/package=AMR)) @@ -67,7 +80,7 @@ This package [is published on CRAN](http://cran.r-project.org/package=AMR), the - R favicon Install in R directly: - `install.packages("AMR")` -### Install from GitHub (latest development version) +### Install from GitHub [![Travis_Build](https://travis-ci.org/msberends/AMR.svg?branch=master)](https://travis-ci.org/msberends/AMR) [![Since_Release](https://img.shields.io/github/commits-since/msberends/AMR/latest.svg?colorB=3679BC)](https://github.com/msberends/AMR/commits/master) [![Last_Commit](https://img.shields.io/github/last-commit/msberends/AMR.svg)](https://github.com/msberends/AMR/commits/master) @@ -86,6 +99,85 @@ library(AMR) # For a list of functions: help(package = "AMR") ``` + +### New classes +This package contains two new S3 classes: `mic` for MIC values (e.g. from Vitek or Phoenix) and `rsi` for antimicrobial drug interpretations (i.e. S, I and R). Both are actually ordered factors under the hood (an MIC of `2` being higher than `<=1` but lower than `>=32`, and for class `rsi` factors are ordered as `S < I < R`). +Both classes have extensions for existing generic functions like `print`, `summary` and `plot`. + +These functions also try to coerce valid values. + +#### RSI +The `septic_patients` data set comes with antimicrobial results of more than 40 different drugs. For example, columns `amox` and `cipr` contain results of amoxicillin and ciprofloxacin, respectively. +```r +summary(septic_patients[, c("amox", "cipr")]) +# amox cipr +# Mode :rsi Mode :rsi +# :1002 :596 +# Sum S :336 Sum S :1108 +# Sum IR:662 Sum IR:296 +# -Sum R:659 -Sum R:227 +# -Sum I:3 -Sum I:69 +``` + +You can use the `plot` function from base R: +```r +plot(septic_patients$cipr) +``` + +![example_1_rsi](man/figures/rsi_example1.png) + +Or use the `ggplot2` and `dplyr` packages to create more appealing plots: +```r +library(dplyr) +library(ggplot2) + +septic_patients %>% + select(amox, cipr) %>% + ggplot_rsi() +``` + +![example_2_rsi](man/figures/rsi_example2.png) + +```r +septic_patients %>% + select(amox, cipr) %>% + ggplot_rsi(x = "Interpretation", facet = "Antibiotic") +``` + +![example_3_rsi](man/figures/rsi_example3.png) + +It also supports grouping variables. Let's say we want to compare resistance of these antibiotics between hospitals A to D (variable `hospital_id`): + +```r +septic_patients %>% + select(hospital_id, amox, cipr) %>% + group_by(hospital_id) %>% + ggplot_rsi() + # start adding ggplot elements here with `+` + facet_grid("hospital_id") + # splitting the plots on our grouping variable + labs(title = "AMR of Amoxicillin And Ciprofloxacine Per Hospital") +``` + +![example_4_rsi](man/figures/rsi_example4.png) + +You could use this to group on anything in your plots: Gram stain, age (group), genus, geographic location, et cetera. + +#### MIC + +```r +# Transform values to new class +mic_data <- as.mic(c(">=32", "1.0", "8", "<=0.128", "8", "16", "16")) + +summary(mic_data) +# Mode:mic +# :0 +# Min.:<=0.128 +# Max.:>=32 + +plot(mic_data) +``` +![example_mic](man/figures/mic_example.png) + + ### Overwrite/force resistance based on EUCAST rules This is also called *interpretive reading*. ```r @@ -132,69 +224,12 @@ guess_bactid("VISA") # Vancomycin Intermediate S. aureus guess_bactid("VRSA") # Vancomycin Resistant S. aureus ``` -### New classes -This package contains two new S3 classes: `mic` for MIC values (e.g. from Vitek or Phoenix) and `rsi` for antimicrobial drug interpretations (i.e. S, I and R). Both are actually ordered factors under the hood (an MIC of `2` being higher than `<=1` but lower than `>=32`, and for class `rsi` factors are ordered as `S < I < R`). -Both classes have extensions for existing generic functions like `print`, `summary` and `plot`. - -These functions also try to coerce valid values. - -#### RSI -The `septic_patients` data set comes with antimicrobial results of more than 40 different drugs. For example, columns `amox` and `cipr` contain results of amoxicillin and ciprofloxacin, respectively. -```r -summary(septic_patients[, c("amox", "cipr")]) -# amox cipr -# Mode :rsi Mode :rsi -# :1002 :596 -# Sum S :336 Sum S :1108 -# Sum IR:662 Sum IR:296 -# -Sum R:659 -Sum R:227 -# -Sum I:3 -Sum I:69 -``` - -You can use the `plot` function from base R: -```r -plot(septic_patients$cipr) -``` - -![example_1_rsi](man/figures/rsi_example1.png) - -Or use the `ggplot2` and `dplyr` packages to create more appealing plots: -```r -septic_patients %>% - select(amox, cipr) %>% - ggplot_rsi() -``` - -![example_2_rsi](man/figures/rsi_example2.png) +### Other (microbial) epidemiological functions ```r -septic_patients %>% - select(amox, cipr) %>% - ggplot_rsi(x = "Interpretation", facet = "Antibiotic") -``` +# G-test to replace Chi squared test +g.test(...) -![example_3_rsi](man/figures/rsi_example3.png) - - -#### MIC - -```r -# Transform values to new class -mic_data <- as.mic(c(">=32", "1.0", "8", "<=0.128", "8", "16", "16")) - -summary(mic_data) -# Mode:mic -# :0 -# Min.:<=0.128 -# Max.:>=32 - -plot(mic_data) -``` -![example_mic](man/figures/mic_example.png) - -Other epidemiological functions: - -```r # Determine key antibiotic based on bacteria ID key_antibiotics(...) @@ -318,7 +353,7 @@ Learn more about this function with: ?freq ``` -### Databases included in package +### Data sets included in package Datasets to work with antibiotics and bacteria properties. ```r # Dataset with 2000 random blood culture isolates from anonymised diff --git a/man/figures/rsi_example4.png b/man/figures/rsi_example4.png new file mode 100644 index 0000000000000000000000000000000000000000..2766db1c39258a85546cb4c0d4e28c7ad25e430d GIT binary patch literal 21185 zcmc({2UHd5wl#_wGm4@TMUfx^269wD5G5%|i7FWclqlI&5EGz8$pR`WIZHMmN=}la zIqq`c3pscbpA(Y(cK+SuSN)OG}63!;lW`&U229VU0W%qV!v^bQX@e*3U4K8}~x zTPAjXJiBWoX|~O(sI)p%%WY}ixN^Cn(3PB$lCqmq{i*!Rm!GmM+OinMoNhWh3pi4i z)tK-~EHBKc*_l^Z*Yh^jKBm^x(lU>&_LW%LOHEy$=U~OdlZ;P0&I|+w2W#2CC4J*9 z9?7h=7BPE7)0)@dT-MMqTS8~$GLbWQn3FTiVUM?!m9B!grH_IDMdl3~TZ+oz4u`JY zlB(+JZVOYNQ&UszM6R{JooX?T$~0@wFjXng(kgVxam3R3tnsnppq@<)Ja@TUF zNApXiC`P>Y>@m&@>tKF$c7}1Qe`#OOh2<`xFn)^%zP?PNH@`2=b#*1__G6X>M-r8#iv?57yS!s#kAfmXwlmo}19Y{bkg7mNJaMlH#Eht35()k?Y{$bYeb|A=q&w5G|^*}}NG`uetPD?JsJdh5KD z+Rl7hC)wuyX4^H&bb~^rVNaf%*U}QP8~IwaG@Bgd_G=iIoFFVZ{pFyn4}EE6W#%E%a~CliI90+S@CP8xJ2o>@+vw+T}VY z=f^UlZ5rV3Z!;L-V3yg6?d!RDPvh6GPw%8UpYm(4bMxBHr2F>zw_B^$xVX4XyzTYD zHB^yC?0xT!Z?$Yrx$?dHJ%fn-BOf1Z37W0Ju2HU}mPh+ejATt>UFIe_?7VFHzU=Up zQPI_9WMXpfuxqj#Z?#+aIrZ6>DSK?b*H=P(s+d|_TpZgifG%vI)kKr=;lqdietu4~ zBmLjL)n=ME$@#M`E|DjL!Yt&C#u@u=-@bjHnoZZC!%j1ixEUST00mMeXHK2^O(u4@ zJ;z3$|Kj9%i_p8$&X{u+$Fb)>&9sknyIq>wdQ?r{I`eu&-8!M{DIe3ii*n z_1=|IOGzaaAtw&W9p>P`&d!d;3-}LeZhWYuHifWT~abKcd2^tYXt>`2vNs0s;dZ{X_aaBpfCZerHQ=BBtyzY z@?6w$!?L`|!aTEvH^?s9xQ>ooJLlO34FSvcy)-oZCNmp7dtGywF|L6*iY$hi@$#S z`0?AC4VtVmrm`PP*7tw=TwI(#RYEt{;h=}x;X!3+XlUo4s-rVLFc1_K)uqf5gwv`XV2cX&tMstj$S@_;lc$&!x!VWUtKLOGG@Q* zPks6FrAD&ucw4rwukUhG(Gs6kXFi=({!~_*<%#6xpB1fwUl7<4!gjPG_SekJMr^9Z znqHjSqoh8`wj4+1ifA-nPY?(Kng)B1v`oV(--@kwN@K|e8 z{p6smCQYWsY-@^3bB1W7xT~}&~ce%~X z%;YUEkw?XxkS=8&?LDumYOwFFH*s^lTRcN@!n~yp>wUPg?R9>>C@ZVXl6mwox#YP( zD}g-$t`q^p?d*Pk2d~Ot)gs(+$$J?Yyfz!=(=)N;TG^J{B^FZJ1ua@LZr!@Ysgd+m zi?nF)4WHPzZ(m2ALzJkab-^m_LYI~|K0;1EUdhBBQ##kYc-^XkiZt0}<#zMu_bXSX z_}0x|Ie6y@3kMHRbw@`>Tbl?sch&JNHsK8o4JdKb@_u7IpB`eJrq}&cU?+={$I_h~ zzV;y>ujkRpW${RPw17N9Be`qOo~DlTYHES;@uO;$qzJ(ql9X32ah~)0f!HGr*MDxG zxwBpTsDxc+^46J;=B2Th3=R8H@^|jsS;6BQUzXsVFgwxV{PFJAAS?g#u`q3Wi^UxLwuJ`-O z3h#0sr{gmV$nl*|pB;{iBK`Ow>b~T1`n0Edd<36)km?|>vXt>dev4LvrGV@MN*)*8 zG*p+i5B!|!RbQn|rW)B=Hyzz^*$_q7`Yfw1x3T6_1g2jbo&S%!W#V)>uiExeXa<~c zdC?o;(78hrIpou{(!!T7U&hA9>f@BO?A-dE$f5*^|Lnelgb^GZtk=-djWeLlr4iY` z|0E^za@T(U;C|8o!)+b!jRWb`;%&Kh=Dv(#Mio!56oz;CDaO^C@J5Ul}R7EnBwik_;DhtZP58y(l`_R$5y6OZt6v{INAmOi`mrc~x&Z8XD9n zuh@-FBFNTl*bv5)W!_Yk-`>|$lG%5o@5_^ki3vIZ%Oi&mmsM3oA~VdtUfCK%>PJmY z{dMwnQc{)}JKdON&GajN?+z&^RJBE<8}1`V7LXtp7Z(p6JlIb`iyPAX1r;WtGT7CR zrGPw<$IQ%3>=~xbzM|7-EG#UHj9#iOuUfNy3oWk+wjCY+wV{T1jhi=b_RjTBOmJ6k z{n|e~ypM*4G!SMLs#RB4ha5FIJlrxSl~Qhb6bW1?|R=sdWq)X#f` z(q2DnhrETwxW`87T!%?rU0rUuy4&kEw`Q6fi@O@-1Owii@`iG#yiCx{9J$XH350*b zsNz-IxLL3T)8m&6TjOcw-JGe}6tz>Yo>o;=?J9Kjq(Txj@8~GSTC}&fuiwrnYTlR- z7v&~=;D97$ZMId{xnS;w4!28}La1T@5>c~UhhGHK@aVQD>q+S8b>+t0sZ1KlyfU9+ z>X?t4s~DFz80p-YaEYkc&CM4btESPI1o2!lmoys9q8G8RXlo-UkU&{yhTx4d{w%x)xL!8ki-n~6aS z+p^m$@5`NzgAvS9chLuJ-*=ql;K7g69CS<*3VS8>uUfM2ov-o)w0^yif}H5Syd-sZ z3*sXwFBo;O)4H6iv$Ipo>Bmzdj$&Q~agsyrc}KF)*4(Ihb_)2dkUZh9^pjD@`uPNZ zrL~RC=STbMV`aCamBKZ=c>WwaEVXmIyr_ZPAFL;ijehFXDdC6-gjse1$0&nlFY?&- zu%OQbrUt;BBayak+*mt0+uz^6UHs>>s3<)-x%=(QW+$|)%27LGVq@2=UY(&i{_1=z z>Nc%#zBdQ?npH|pnRuxY_cnUL>j1*Pe*XMPCQE#Ow`L$iSFKLv!i8Mh;ks0P+4<;k zZDrCbWj~o;GX`sKmArMCPs`4pQ<7Nx8mGi0`+2qJV_S-<=t{k|4eauT6`S8k)~yoU zP$u3zqP*%AmE4AIdUo=y_}-C`T$g$42*tsnlh5e=w!IU&Zox!BaqIBWwha^%&o-g% zQc%1(+46t)hbANRm86jd^SbA9KHJuo4L2rgVK+IG##&-!eTx>yt&qj7ZKajJyuY)7 z35i48_16{#VcV&mPkelQK0cIONvL?!z%V^#6=m^<(o1H+Dh>(hOurT%OZq-OmM+vsm1&e5xI z-g)0W^z7N%8L}7$2gk8vQ{TUR#9yqso0eSJoNG6Vok^^3wK%z=Hua>bo12?2wgQ>} zdIrjX@4rTqCFcA50okp{q;V-p$${#qsNmp19FZRT2x->}7a2e{u@7*ykWy1?K$|oP z0Derr_)*YY;ls^&SO@eeryIV<2?XeP_Pw&lY5Hq&(93n zSVWy&yKY@zK)_R`Q2CcA5J*FUM_JgDpFd~WzyDqB`FAbKq|8+Sqsxnv?laTVeVZ<~ zq!|LG*w`v72ZV*SA^G{x3-u6}1q_K^?J3hhe?OO2R>jAUAAe&$<%rIlk=NugPBA@t z%zTYFI1b$cr+G5Dd^@`29OLT9&3m{7`46+d&dMTv+%A!imXx^fM{&~vIW>rj03k6{ z8;dab5$h}drq+a>Vb87$=g*_Z_31AU9-VbUXc&LYbhUT~N(D`rq1#@1`gUwPqJ7ye z`u*0L*xRe+SyiwfJ*hG?Gtm!eAM|X1Es#7$!mfhnq3&)8QHpr`$j4Vhdt#A3rG|oSUj@{@f zUZGCX($ao76##8f9pLBZM@Sz&{H9ZeS^CPAXqnh2EOL}jA|e=e?D&S3yQZ+LtgI?r zsD4c9d??cy2~lx9$FhvYKIA;~6oMJUE-;V%n6jK`G9sw?#5KDzA-iLvOjAuwg{`noM+rKjHpe}RuGhnFniwrD zE!ok<$H$jChZzY>Y9?k`_F_+dan>>xnFXov;PmYQ9`Xp#Qu zpV69xU6SCUDH-IB+ZO$BaujHeY&7B_z8?|t_UCYPI z+qQb;b#3lO&z;_4sr1UOuA)xs8b4|#dN#&T3*rXk#SlO24K*VqhyrEVncsr*lz;i? z(Ia5yyR?RZfq_CoLIXkX-o1PFZ2!8RwO~K5o(=Cq=Azc#(a84 z#zK%SG@C%Io)r5TNbsuvl1csd9P9t$Zv@tnZY(X#^O-lgpjeEzX66Cr#L0)$VUpB-10?fvaO)LRsq&$*)Ms+gtF4Bcti1$Im$QIpSRKpuV6t5@twN=nSq78Z#)cUa_D z{pBckU>DhsYvvr|;^JauWyK=!@u~Se@9Q&|H|;4lY98mV(5 z^EO6N_T^)7^~0MsZ${boph7ZQwQ5yR{8(3!1TU{@d;{&4yT!%Q%pSES@=8kCt!cP> z#MWc;Q9>Pzmuez*s=4c;znY>+4sRBX`GZBwM!p#2Zy_ z=?&w{e-TCwC5=mMz7Y{IG(?414|{)Y1$P3{Qc%2FZMgEobqhVZtZA=o28IurPS)Qk zWxcRZHU9=p-^uAxP-t>ke)Syq^e>L^x5Ir`Sa~noTdtz+s)fXj=_}y&-8H6~lIu)7 z6esKdcI3Z--e)x$!h{ea(B(3Nd-L0Gzad*L{+f+{{rXao+akJKW{qM?^;wa7vtj*0nD;Ulh`V#jaCc2vfT~7e2 zftAc(094-0eD>Tq@Ok|~-QC@Fbr+aDbdv@4Zkd)uzCw^mO5XOaM4wJ{o-$q{p@*Dg zMXq8@Ggz5I^C-Q7LDL;@rbU|*Jo?d`7uw%27I5%0JxFo`9qAGTHZ z9;}KGarv3@=b5GhRf79(Sb+`rWBA;_oqCeQpl88XFAopf$xfZr%c_deX;y%L=-n=> zs(uB@`^>pwTR+*YVnw*+V^E z&89P=+eWw9xx6XNA%n`ZtPq)XHpDox)+`f*&N8;ACzWtSQcB8E78YqraICwis4lml z9bSx%j@C?UynK{}m30#{=m{sMT)Q8ZcxBzaY&LL1@UDwyI|rYIiTw-1{f+!0%9n`X=F)FB7{%a%lFKVR=yL<}wec!rcM8 z4wG-+xufScZ&*(AkE9dv*Q7H=B%N@EqB^9K|FDI9Rx=*DiZ?h=B4a+v$o-F$V^;j% zWtP9Cng8gA+hND^_MI?#)c+CM?c0|xjj&_&T&6s!uKxV~&7V!l-o~c9vQh!es3Z#u z%N9C*dCK$J+W9D-P@?|4t*^$~(hMKwe}}{gP;%}ciGZyA6--r8#nO zzg%6+>4%Ui4-pt5oZlk!_zH$N=2<4Lp`pR-!6FBdHdM?xi|PO;=egu2XGh14%vbgG zRa8`BV`4n0JUu-jS^KdtOWWJqOG|rrdC5wJadC1Ix`y}SUH-|V^nF-bpKZ}Eni(|F zSLPQKB+^z#h-h56aMk%V+nIvU8OB|^`bJ018*YC4;29Hhpp8@bMyK=a1;NJy#sZVr zx~Tl>-biY~pnq0Ew(31;NZ4Vb{k00)r`zX+aIP(&3)XMhTa#mB%q(qcYDz#8M$u@! zPk(v==;^gJH4hWWbN!uDy6m9ytE-jHoJmQ2KQc0cE;7TVds}1oUY$Vi*mcbcddQO< zCD@pc=lClvfAuMC|y54t0Z3k$m*t}P36W%VD1 zj_p34+0^HSR&gMXMGkOT@*bL7K=(3loY%2q$AAxBzkcnROSP-IQ_hXe+Lb)3$f53H$30hl{jOwqyzJMB zZ)nx2y+1RtcG98t>(|&r>~jj8gtRo;Sm{!t9#_AchNi6i5A+c+H`&EROZ%q5Z0mZU z63MGqV_bIcM|6bBNRWb z+`hf*AvG`q2ZybnhTn6m!uf&UHZUH|mX?(b4h&R?64&v2e(&DB+F04JC<2!Li?B_s zDP!uix20?vDSdyCo?-PfdlUj%Z==dkz923TbWNq_W#>IWLUsRkuDRP+A)aQ4a)L7Yh=k}ZJIA!8IU%$cv*;kqI&_f zXD(FR#w^)#@oLc-c@QI-ye!!?9fTu=Rv$bESHWf@oaL<`(G>_$}Qi>H7TKz|XI2ncr| zGIKj0GCRrAX%qIYq@FCbZu(U_5nkbd>kO>L{yDPs41dY@?jdPy@kUk&(M@f~>ShNreXi znQ0?)Ld@|n3HK#@08;YXDbU;; zkvf)gbE*eS7DPto;>XNV+Zcp1tosR_T8nZA9UZyiL^UOI-~DWG3GH@GI+FL$d%b=8 z76-W$8FIoQy@2nMo!u-50Z1RX$Lt7Yl+OM<_l560eyRa$XrKzcz9p;@_3W68?3KC%U)lUyVH~K}yIIba4H+Uz$mZn}^zn)mE9qXsHMRFswXOElCtn4*E~+dXQZp30YwJ7QY@GD6742tZ#e>ssoLFqaQa zE?Z;rFLx$)M7J2ljcKJ^evfmLfQT6v>2#K|7Cs(O7D-y!6K_b&a&*>Ka{ZoAd1FVOL7vwV~-R!q-Z`Qw5P}mFF>tq3Rw6yf}7ZOOJ zN7&fnIwMiFU*xAi{y^IX3W4?7I5y73A~#n>#VS-Kf{n8~6czaH-ATM5xoAn#?I&~} z@~>Zwd0nh2DkKI8Hy2z?5EoE2CpUND8&_g|E?v6x5RQ#>BkzX~3Db%vm5BWqJ3ISP z!djL3?Ac|2KS|1eO;BkFup(rIu}d{BUPQGV2r-5Niyqt>W)i4uTj>Rl9y}P^sb*9a z4#<<~O13Z1jS2{0sh+=-n#$+s3&f2p*UL0hb8{m$dw)EIFN28D?m+q2T2X*fh&avZ z#!B|~BsftbZ}x1=6Nt5B5z!kSYRjH<=yDaf`Tep@Ig)4cNY5$eVjKaPr4>Chb1{Hi z|C?j~FGZN!BRxI+;DG}W(~_)}u|tRddt9GNwgl5Jn^+W|2a)tP1!x7L(dxtvf_!2ZgApD4bRdj&kG1)Xd36joqf44K;gb%64sgKHnl2MK$e`vKxG4 z9;fiBk%n*w#KoVS1QHZD2{Ex!f?&LZLnt5F*<57R1vQEA7IBf0sAdlOiuR0;b9vl^ zBFp4Fc8uBMcM?!<)Bk{<&?{h~HmbT27qWhNiy4_|g93STH9Eu2w0C~g&m;4-rlzOU z@(ws!RfYyRASF$AHfC0pisnJn+(Sz{GQ=Jl5|O4$s-Tem&O4(OGXMkdqV%%^c)HXi5l4C1mO1dpqDJi*jGesWs6? zlsh`kL$-}{nJz79S4~ELhaO*Duj;y;oj2@8zP`zA5`W<_OT5?NkXzGKNW-(g;ARWu z%mP#b6HQ3;OMU)I*lyxxU)kZ092seyz5zC`JG41Rd=e2dpy%n|0nri#dbi{jM$xx# z-i(-8b!@=_y^ssx4rv?NAOqnrsc6ZGxwu+lc?`!uF{61zu%?y8RdStZR}KHXX*YX0*^Qgl(+QMd-kR9@wvlUgh|EqSed6(zSPVl$V!#Qeojc z(v5woVz7ufaOUbK#5?x2aFFkA**6Vq)nI@BRtDi8@P)t(Gz2FXQ-osN$~pP;4-5=| zzrt%`0tuuDx3;}@2VX>l)ik$G?vG^m#Zi#Bf9Q0CX8{@=TpFsZf;d;N_=JRjWgU=0 zNU%%j$b^JrSkq3lIn*l%?B2awAwpO!wl*Jz1bm)@lamf`dFAXg&K^{#|JX~B9o(Vnc#=Gn26HKX$>j#>({R$llk?vzwzoUvN<9x`$a|Z@Bm^} z2PwJY7IAaiKRAsuii@r_sn`r=pg{jl4$W+^DOM>hNN55bw*I(dIT6XW#4ow9w@{4KD9_I=@oG3bcA>W-6kbP1m<%9xAwP^ZB`+f; zJgCq?!623v7N!L{L{l@A>HstI6?jS|?*Zw6E>;TV9e!gE?v#R)WYt}FBu~h3x(|4e zL+>Da*ND@flGu65DY#Q0iJgFD=kn1b7gJ99J%?}cMO@rDzW@j#aHkpF$5uR9i7hR8 z4+#Xjd>Rn42sww4AOTK!E~dO|Xvmx*!sC1jCYMpx+ch%Vfx@uBkaPM5XzlBib}m6G0ze z0_=`uY}KvZcp-TppFmlzy&7t25fbj5qz8QkeCZ;*OiWDW@%IhjeS?P~OM_)HF?_t% z(b>8D)4R;;5e37v+0S<3CRbEc07eXZb!yfUouF3 z_3ECluRA)PBhD{hya0bou$g~t@}ctKmC2VM=pRO79DhJ8r?At$*Eh?ohyRMxGIB8r z2H!G8R!B$w<~V{9nII7LRoAFh(@ED^Dw9kdgIUm!x9C2}&$iA|(X;AI?u<0oaxLcD zP{R*EBI3626BeT*S}jYRH90 zG+K)Oq4*(+B`ITTpGHPnW*X)t?-pU&ZQ&6XwrDeDp;~{p@o6!Wo!cf5gJmF@*rq^y5k*MEOMIgUtycdv(}R*i`?Pg+RO|O!+)g~ z7CAXNZLF;;xKPkxpV7#aMMzytRk_8Z{q{PH2FM21JF>7}AgmPp?0Kk>=?iWc?I{Wy zDm(|UE(Zq`9tH*-b#;E%U$%072M!#N@ny7_i27Y`oc|iBo2-|0EhPVXras7nTRL1K)EtMAkKAgW?7i>AfSCjJzI~=bQEVQ6DdIwZDdO=R3^>PxW{D1z z>Q`Zwx#+(&D5qdf1`^3~A*2u!Bm1OrPImUU!!N_ofv`#B_xgws1~+(_r+*`ejK~wN zhd!aV3lAUr_6^Qwt1sJ8j~S?_z5@khxm+d=qG-RV8N!&6kr9et>2~t$=p2#>c!8Kt zy{Nb+(@{nSCnw$E|1J*#Z#ExiheOxgMcG5f_Ve@0vg`mg+X4s3Br=eYP|L{rD&oM4 zW8r-S;y^$mJ~RCMb`nIg>j=yXuB1z+uM!kXI?8{}+qY;3jd2KfXdUPT!T*ddojiN7E<5KmQ>OSKa6=pp!%U z4Ox7yVjP{l>9=?IJ$>@amnF5#ymTUlT`0dC9!~|VBGvL(y zIax}SsSv@3hK80F$*{FBU~~kuj6jI|Ch7I~<3ZnCq^~MU8<}yRAX1b8DRS(f#a|8ejW8$sFiBX>s$BcMyR=WVKZ*AMy{FY#Ddfit$`LM5{mCrpF4XN%$X+@vPFo1Rp&#V!dGXm z;q#=#g)1YO2}^z5nU%ZcIE{_7{@9DKH9YX~X*A2kP8>5&E+ExNZRen-Cr;&IM2k3c z@$WeP#Yq%r3KJpHBw@&+U{iK)ahRX(NBV?a6u12b;2pB)CNBWZTLWtDEpxD^7#JAr z-EtSW4a&(is7{q>>2MArh`yAg=D|gTu>!pC&GaPw;9ooV2_%zz&;~{=A~;@XgC3~> zPHYZ={eTQpb3|5fw!WId`0-pNA_N<%ilDzYw!Es525yblHb6>m)I#6^OwO0!~bK#SohdeolIZ^Ytx7zm;c}S66odn)@9(cZ80s{)n7ksliT3 zaQMkOPf9QPrC53XId#2bTr@s_Oxx*R5T9F)0n(1G8O;>gGrHA_4BC zrtXhlM34mhfQ12j%N`&Z*wF1qtt`TmxCeZKZN{@I^w`qL{U4p;dgw6T0fM9COF6dh zBI>&*6~?jJ^BreE@_ABWaA4ZEs1!aRlq|fHSpv-cR})_EE>wh*Hl|&Li=b4%zs;cJ z#XWy6AI4wVk~E(8=1r0*+@0lRWtfHImb)M=T?|R2QpwQB2q{LFd-jLZA_hbHJcG7D z4u1C_Ie8KUhx^B^0#F_oy#+c!4#7fZCJc={okeMOBeV93Q3lq4QPO>HZ$2I`ESYYB zW^^|$cPSbEK!^9Y*MYf9NKAy1Q7}^_!hp-2>LpUpR;Vx$d3j{OC5&1{1P8NqSwHu_ z;FJY2{n^$j5{bXd=y_r+W*0LolG3Re7*^NtU-#RCE8HFKlEuT9R)BC>uOtkn+oV!` z>3deJ)LV6>ZH(WBsGe=A_^VzoI8UhY-9IAf$5^^DEKL9Q%l}9g`@;b6x6iy45~g@| z`fZh>tu1x!K2H`{8Nwd2_~_+BUeH7-WE#R1BhTD&@#&zD$LqGtq$jGm$~ zS#KGP6eTkVT5-o|0|9|-*rpMH%+ivQAKF8Od2O+glHC9 z!wUQr$j9YhO+_C60mE2Ec<8!|AzNaHTILSFgl7!%pS`^YJ-(m>cze$x(@am}o652> zKW8{*X!h(m=f~plrK-y39w8+uv!1~!vc0U4>x`E2+QiIwvwM}d%uL-mo{fL%=f)7x z;XL%Daw_P&eDup^p!NCrc~BGl{A6rRCJ5+_J|evJ6!c~Q%fQei*`~kB=U{4q<62uX zR%|D&QNLzKVP#36Mc8a3K=db(q(cdfrz#yMF%kfIAdwb(8)rRst@ZwP#WtqUl;B?w zI?xJp?ta+H@hi{=ZH)VLDH{ywj+iDhH#e^w_hSi>XJv-r=qDJW{t{FY2oG3+uU}Q= z{J=9Kc#jb3MrCCq)%4j==Pf=pu#h;lMO?OpRxTe&m$i~yIEAO)-{^@BnMcFYX5w%< zwW#z|CXHEDo_c&@+tB!UCAlCmJ>nEdvrh+pgIVa)!#z!jS^!?{u=zv98HHrGM{>wE z7Z?5bF%`2k+NYBzZ}lGrbl$#oYlB(l`a8_Wj-98x!b=O^LSoifZ?B5grSHo&4+P{p zB;1#yvLtfXdl~t=Slo(G{N2yQ?+72IlT+)2zS#xQ#7&Obb%n0ZWa3Os$x_q`3covc z&^V#k;zjr)zzh@s2mYCG(h2!Z9tr2klP3d9|Jr9)LBfcDaipUWY(Ky^lMv9+nRrlP z@D&UX486fD90v|uMRPl_6cQ2w{-w!;SCX^;g78Tds?!SnE z?Ex*77%c<=Faw7M;oL}WLJe>F`ZYnXXbCusN^%R6xC^Y_XzU@yLX(xe=i%W2rg(y@<|nF>7^)qB@Fr&avF7v2%9n|GZT(ZH-lL3p zQemSUI%L?H?1O@UghvQhAhNh;l!I#H?GR(!mQJfk#p;aJ6 z%gfIZLKfVfw7Yj7@&NKdQSoEh$PBsUcRnBOJN9jLltl77D*E`8l$u)Rj9qzBGjns8 zv@KBU1-^x%)O2-a=Q{(Nfe22d1?2+Id)x2-ig=hMk+RGZ-n{t*DoXRntHuxaXSm0_ ztDuB`{wzxvT<)hO!!-sy^AS}{Ru=!kgS{XI_Yfn1>o;sDXMoY-UuTspZFP0rkYifp zi5hwR>#vYJ8keQpm~{SV%h75BA*ScWoFMF|EBQntdknKZs~xTC$6h8w;I%6+1oV3{ zmsMp?NYm`(U9mNpU_?N~5ahtSTdP!F%I}c;+SnKxlY9nenfBFm_tzTEjk5$`_Q@Gwo1`0Mz53kC@6Mn5zhsXeZ09p7Y;k5kqQtimim`3 zKU0iLhplPFEgSOioLEzo?L>Ra#Gn4e*?|Jojy@ujymy-Mp+Q;6h6@GVSyd=sJa_}^ zhbu%ne6u?wcm0k>NL~M?yS@ben=fCxy*(hlYIkEsG%ngFzwKmaB79zK;;cqhVlsn_ zaMlzXn_Ri_jqn*6l={KTj&$jG)e2K!7}*VCGBPlbmXQf1Yy4fCzei~E_c_krViL9; z!lu1<|NaxE+_!IC!1(`Xi2=Ei;D5m!YVqaf=9YXWUQOdnbadvr+u&4&WvaXcO~|v= zRqoLQ4ZU{7rFZskMf(4jAJ{cWaH@U!{5gyX^Wx9r;y$C0fBFQ{4QYUq8FoC(CF2Ek zjm-hVA-wJWS66H=oUl(pm|pB^(SR7nkLkgRlr z{+nnMg_Akn8}jnooEG{IfkxZfm}%+t+n6FEer){KbD`QJV-cj5xS*nFh6D=MieB}H zfz0`J@|+DLSMe3YsDBC{@w~snd1`7;Dop5#iFKGA#43O*O!qD@SgdKkAtKoUS%CUc zQgn0+%*8}s+B(tuyL~uJJs$Nti!8VT5n2XdrG<+Qr*f2c#VaG2P>k`e|7wtxP{UY* zzrViaM!@?`o2-?eVsk5gxRUPrF9IlzaA5i}@l=yW|1hTcY$8nU8`(8Uu86q-!xdNB z&2o|X5O}Wt^s^*N6LN>5_b5Ax@c)L9<-e50|Hv@&zVf_C(tqe=^?5)f9wEVNSyq3N z-~VSGM1}Io(Y=_)bU{6245_DU=DoFq=!?R92JUq>ML8B@Gk*cUCME~rtitQTr!jVr7r*<;LSamVwr|EVX%W#84chAM+l$NR&k|H+ zzm6XZ=AMWes2J{W#maVefPvU>djD;hJwdrK$5Lww_i?3nA7LKTTGX>rZ)6iMzro?W;#)rThk8-5$4Jxy;ygYs7 z7Z&a&u#f#8mHF`8@<2nt+#j@ZWNG|AXl0S-|B_b5tll(;(16Xf59-Y_A;qYBqZtOP zZF@#k`EGKuRfp*kcrXxvBAAW&i2Mx%`z96HJU_pkdFtf8&d$#1*AndSu($uoB04_? zj!jBRDpND@{pB&Mq*j74QirC5+jz zdK~SlJH)|Z3g&0q#+3jQOduYwbIb2%885yZ{{O1dyh<92hr#OTl@AbpLtV?E`KOWt zyglOsqoS65-52!1T7yi(ti*{B`KC0!7QztKtnaHswqGhDO^7{zJ?FdTr;YYm!*cqN z^fZZu3r40pICtkMD?eRJyX!%dT|H|#x4Lcm=1Y`2%se}49+?U%gn5TvP<~u->8#Ht z;}^>&sxLVXn_1eE$h`}~TQYm)nod`fXPayyXTpsKg{)YkB4THZ-Rd)3_B(9*;=1cG z`QBp@YcKc5-DQQa4OL-i1P=>waAuP|K9nIB^bFD^vDq=ms1l*`yi z?-#WuumF}EUz2?-vh(6!4i}|E|5#*U+igxVs0%RM!ACAlFU;GJtBwShkLNwSqnQYV zuzkxGTWjl3@O3D(bhNZGVs!Dz$x26Pd=1xI>Wdbno}8e6OlIFdw}aV1JWp`H!%qee zHBv~WQEctrUArFFmh`N7Yx{#q4q-F_)5!f#yV7DSM~ zzCJ*I1gbSpvB7bWNGV|$?ZDFs_VR{d@~pfcyc1jk)NS*qs3<$z@?L=-kUV2;eO!dA zIuiq8FD~q3V2B702LLXiFLz~dGfma^YJVbPEj#fgLVl?IH?}K*u1HrnEQTj%=jM_z zM>#xv#Q_~6;40DEv-qK{WrXhg?Aa|UzlezOzP^Bn2-leb1zFk8n8Dm3sh+IMMe`6k zHUS~5bEFSk87wU=o%-=Z^|dM-<)Dt!G!qw;CZS$}!-bNGzNY=4mX;Rgsd7HMkV%+3 z!cd$58=KcSvMV0;u#oal*nVs;GmDs51Ve?*IK)y2Z{P^<;W2aXn+!jB?8mTch^yE? zw=qKGJ4-^EQgRb&Tun_4JPSx1NHZyUPy~SN&%v&;amRgWT%}QZ2-O7@75I62!O{;6 z?S(RC(Y9h0Z|SqAzgceS?G)~6ErJ*HrML}l?5BrLssdUP~1e8i=t zrbB0*oGFex!3@&Zu!f@T^o{O|WVB@P9$^-We&4=QAEqhc?|Qi5IHM=z?Kn4^y+t`| z+*cna14YKgv60;#ml|N76ciM+%a$6X0pb9BTs#s4lPQiwEt#M`N@V)8{b=zSMQ>gf zaVzyZ1oysKCZK6Rz%CNk6+JK)SV*UW!lI(0oE#xYYb-1VHNGhj`0-9+9!N9eUUkgf zo*er-@4;pcPfk`ZSZ+TiYrZzeH@^KhiB+D@n?^MfF21)!lXLEH zARY>3!?c@;X&H<)f&mSI))AV4Q6CI#;L#|Ccn(f99t*YjbLyaoZnSc~`?5GcKMB+k ze3J_bR%;-b!-1U!mgTKy=ttwt*!0j$6l+bbql6nbe=xWJId^^cb#Y-VacId`{&n{33rOy zw+L%7#Yw7_szO1z8m`}z^p`JLAH;-5L^wM+{d~0i{o9>SSFg10I^BTSYHHd}_DyeI zRm9tt94dTL8M*3keiwZG(EScSIfKZ-@L7nWB(&-6^(n4L$ldSppb;kUoG>uV z&CaI!A6-*nG=nOSQ8uvFHhBJ2dP~JII)!>X1C4krg7krnn>U+VS}xrQUQ5xfNBFJB z2x|wnIYcqEp_og7BdBn^6A}ZS;e-irJP?DQn>#5k&MW7I@$rzmooyl@?m?MYb`?UR z1xt{6${CL>z%yO2ho)y{K*ro0`N|>rrP_#4?vVAd;vix~goWX|ygKK(hT_p0bqWfR zXw%lVHZAVp6XWYP(_CxKxZiP(GRJDrzWU2;tp4|@V(N#VDuPiR8(UZ; zJJ?ew)L%_~o1Y)PPZ^DJPmg5%kCgOUUYNv^8q7kfpv{37DnwGA)7?yQ%YFLtz`j7{(y*P`o?_j(>+SMzXHbg3v_D#jMqdym;ttd3hp7 zk3Mce=;Dbo*UZi7>?2_qf|~`8@p#ZeJdy+~+^4Hk$;sO(F1v*N$X24DVBMCfsX%%D za9~yhJn#U|^3KRIu}>S{zyFP@XK3gP>0+Y#bg#gCa|ukcDPAYK1`q7KFEdp~K|#Hd zI9=BoUY&~<@u0tt;tJ19Tg%HIzFsFAotEZjD(XxE!O=ikAFX;gg5N?@O>KAjB{j7} zG!I`~7*3fv^Wp-ih&%7!U2AM;kb6;wWam4PKtWN$(>}h2g8T{|IWx1?EDO3esq?Dv zdI6T3o5zQR(S1$@^ajC5n2;<6acfWk;YpesYw>^j)P%gQYS(FwT@PSahYjjtVj~_1 z(6;K1Q7roid~EO;fc1j831t`4ETE&8$1<-|+?pad{$?-D#7N{mFv1ohuoWYAu~%Z0 z+1>1)Nk%uL(8CODY#e8?3_6T3WY*Q~+_B>ZYV;{tY^SQLsTft=AqfirYLJl8IXO9I z5B9*atgI|30H(aO1MiO!@irQYu8U&rswjuwzY@d+QpL(68j%bBeGb6ePOS_AQtYQ( hX{m6KKR&#$oqpbY;iw(WFT9CD?zEzGlH}#v{|``6e=`68 literal 0 HcmV?d00001 diff --git a/man/first_isolate.Rd b/man/first_isolate.Rd index 629bd5e8..24a4e714 100755 --- a/man/first_isolate.Rd +++ b/man/first_isolate.Rd @@ -76,7 +76,7 @@ Determine first (weighted) isolates of all microorganisms of every patient per e } \examples{ -# septic_patients is a dataset available in the AMR package. It is true data. +# septic_patients is a dataset available in the AMR package. It is true, genuine data. ?septic_patients library(dplyr) diff --git a/man/ggplot_rsi.Rd b/man/ggplot_rsi.Rd index 95c6bd6a..5eb020e5 100644 --- a/man/ggplot_rsi.Rd +++ b/man/ggplot_rsi.Rd @@ -9,9 +9,11 @@ \alias{theme_rsi} \title{AMR bar plots with \code{ggplot}} \usage{ -ggplot_rsi(data, x = "Antibiotic", facet = NULL) +ggplot_rsi(data, position = "stack", x = "Antibiotic", + fill = "Interpretation", facet = NULL) -geom_rsi(position = "stack", x = c("Antibiotic", "Interpretation")) +geom_rsi(position = "stack", x = c("Antibiotic", "Interpretation"), + fill = "Interpretation") facet_rsi(facet = c("Interpretation", "Antibiotic")) @@ -24,11 +26,13 @@ theme_rsi() \arguments{ \item{data}{a \code{data.frame} with column(s) of class \code{"rsi"} (see \code{\link{as.rsi}})} -\item{x}{parameter to show on x axis, either \code{"Antibiotic"} (default) or \code{"Interpretation"}} - -\item{facet}{parameter to split plots by, either \code{"Interpretation"} (default) or \code{"Antibiotic"}} - \item{position}{position adjustment of bars, either \code{"stack"} (default) or \code{"dodge"}} + +\item{x}{variable to show on x axis, either \code{"Antibiotic"} (default) or \code{"Interpretation"}} + +\item{fill}{variable to categorise using the plots legend} + +\item{facet}{variable to split plots by, either \code{"Interpretation"} (default) or \code{"Antibiotic"}} } \description{ Use these functions to create bar plots for antimicrobial resistance analysis. All functions rely on internal \code{\link[ggplot2]{ggplot}} functions. @@ -74,4 +78,12 @@ septic_patients \%>\% septic_patients \%>\% select(amox, nitr, fosf, trim, cipr) \%>\% ggplot_rsi(x = "Interpretation", facet = "Antibiotic") + +# it also supports groups (don't forget to use facet on the group): +septic_patients \%>\% + select(hospital_id, amox, cipr) \%>\% + group_by(hospital_id) \%>\% + ggplot_rsi() + + facet_grid("hospital_id") + + labs(title = "AMR of Amoxicillin And Ciprofloxacine Per Hospital") } diff --git a/man/portion.Rd b/man/portion.Rd index edd4b58f..572e847c 100644 --- a/man/portion.Rd +++ b/man/portion.Rd @@ -11,6 +11,8 @@ \title{Calculate resistance of isolates} \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} } \usage{ portion_R(ab1, ab2 = NULL, minimum = 30, as_percent = FALSE) @@ -49,7 +51,7 @@ These functions can be used to calculate the (co-)resistance of microbial isolat \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. -\code{portion_df} takes any variable from \code{data} that has an \code{"rsi"} class (created with \code{\link{as.rsi}}) and calculates the portions R, I and S. The resulting \code{data.frame} will have three rows (for R/I/S) and a column for each variable with class \code{"rsi"}. +\code{portion_df} takes any variable from \code{data} that has an \code{"rsi"} class (created with \code{\link{as.rsi}}) and calculates the portions 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"}. The old \code{\link{rsi}} function is still available for backwards compatibility but is deprecated. \if{html}{ @@ -66,6 +68,9 @@ The old \code{\link{rsi}} function is still available for backwards compatibilit } } \examples{ +# septic_patients is a data set available in the AMR package. It is true, genuine data. +?septic_patients + # Calculate resistance portion_R(septic_patients$amox) portion_IR(septic_patients$amox) @@ -114,6 +119,18 @@ septic_patients \%>\% combination_p = portion_S(cipr, gent, as_percent = TRUE), combination_n = n_rsi(cipr, gent)) +# Get portions S/I/R immediately of all rsi columns +septic_patients \%>\% + select(amox, cipr) \%>\% + portion_df(translate = FALSE) + +# It also supports grouping variables +septic_patients \%>\% + select(hospital_id, amox, cipr) \%>\% + group_by(hospital_id) \%>\% + portion_df(translate = FALSE) + + \dontrun{ # calculate current empiric combination therapy of Helicobacter gastritis: diff --git a/man/septic_patients.Rd b/man/septic_patients.Rd index 7d84ee87..cd494038 100755 --- a/man/septic_patients.Rd +++ b/man/septic_patients.Rd @@ -7,7 +7,7 @@ \format{A data.frame with 2000 observations and 49 variables: \describe{ \item{\code{date}}{date of receipt at the laboratory} - \item{\code{hospital_id}}{ID of the hospital} + \item{\code{hospital_id}}{ID of the hospital, from A to D} \item{\code{ward_icu}}{logical to determine if ward is an intensive care unit} \item{\code{ward_clinical}}{logical to determine if ward is a regular clinical ward} \item{\code{ward_outpatient}}{logical to determine if ward is an outpatient clinic} @@ -21,7 +21,7 @@ septic_patients } \description{ -An anonymised dataset containing 2000 microbial blood culture isolates with their antibiogram of septic patients found in 5 different hospitals in the Netherlands, between 2001 and 2017. This data.frame can be used to practice AMR analysis. For examples, press F1. +An anonymised dataset containing 2000 microbial blood culture isolates with their full antibiograms found in septic patients in 4 different hospitals in the Netherlands, between 2001 and 2017. It is true, genuine data. This \code{data.frame} can be used to practice AMR analysis. For examples, press F1. } \examples{ # ----------- # diff --git a/tests/testthat/test-ggplot_rsi.R b/tests/testthat/test-ggplot_rsi.R index e46e24d6..ee4bf8fc 100644 --- a/tests/testthat/test-ggplot_rsi.R +++ b/tests/testthat/test-ggplot_rsi.R @@ -32,4 +32,13 @@ test_that("ggplot_rsi works", { expect_error(geom_rsi(x = "test")) expect_error(facet_rsi(facet = "test")) + # support for groups + print( + septic_patients %>% + select(hospital_id, amox, cipr) %>% + group_by(hospital_id) %>% + ggplot_rsi() + + facet_grid("hospital_id") + ) + })