mirror of
https://github.com/msberends/AMR.git
synced 2024-12-26 06:46:11 +01:00
194 lines
7.6 KiB
R
194 lines
7.6 KiB
R
% Generated by roxygen2: do not edit by hand
|
|
% Please edit documentation in R/get_episode.R
|
|
\name{get_episode}
|
|
\alias{get_episode}
|
|
\alias{is_new_episode}
|
|
\title{Determine Clinical or Epidemic Episodes}
|
|
\usage{
|
|
get_episode(x, episode_days = NULL, case_free_days = NULL, ...)
|
|
|
|
is_new_episode(x, episode_days = NULL, case_free_days = NULL, ...)
|
|
}
|
|
\arguments{
|
|
\item{x}{vector of dates (class \code{Date} or \code{POSIXt}), will be sorted internally to determine episodes}
|
|
|
|
\item{episode_days}{episode length in days to specify the time period after which a new episode begins, can also be less than a day or \code{Inf}, see \emph{Details}}
|
|
|
|
\item{case_free_days}{(inter-epidemic) interval length in days after which a new episode will start, can also be less than a day or \code{Inf}, see \emph{Details}}
|
|
|
|
\item{...}{ignored, only in place to allow future extensions}
|
|
}
|
|
\value{
|
|
\itemize{
|
|
\item \code{\link[=get_episode]{get_episode()}}: an \link{integer} vector
|
|
\item \code{\link[=is_new_episode]{is_new_episode()}}: a \link{logical} vector
|
|
}
|
|
}
|
|
\description{
|
|
These functions determine which items in a vector can be considered (the start of) a new episode. This can be used to determine clinical episodes for any epidemiological analysis. The \code{\link[=get_episode]{get_episode()}} function returns the index number of the episode per group, while the \code{\link[=is_new_episode]{is_new_episode()}} function returns \code{TRUE} for every new \code{\link[=get_episode]{get_episode()}} index. Both absolute and relative episode determination are supported.
|
|
}
|
|
\details{
|
|
Episodes can be determined in two ways: absolute and relative.
|
|
\enumerate{
|
|
\item Absolute
|
|
|
|
This method uses \code{episode_days} to define an episode length in days, after which a new episode will start. A common use case in AMR data analysis is microbial epidemiology: episodes of \emph{S. aureus} bacteraemia in ICU patients for example. The episode length could then be 30 days, so that new \emph{S. aureus} isolates after an ICU episode of 30 days will be considered a different (or new) episode.
|
|
|
|
Thus, this method counts \strong{since the start of the previous episode}.
|
|
\item Relative
|
|
|
|
This method uses \code{case_free_days} to quantify the duration of case-free days (the inter-epidemic interval), after which a new episode will start. A common use case is infectious disease epidemiology: episodes of norovirus outbreaks in a hospital for example. The case-free period could then be 14 days, so that new norovirus cases after that time will be considered a different (or new) episode.
|
|
|
|
Thus, this methods counts \strong{since the last case in the previous episode}.
|
|
}
|
|
|
|
In a table:\tabular{ccc}{
|
|
Date \tab Using \code{episode_days = 7} \tab Using \code{case_free_days = 7} \cr
|
|
2023-01-01 \tab 1 \tab 1 \cr
|
|
2023-01-02 \tab 1 \tab 1 \cr
|
|
2023-01-05 \tab 1 \tab 1 \cr
|
|
2023-01-08 \tab 2** \tab 1 \cr
|
|
2023-02-21 \tab 3 \tab 2*** \cr
|
|
2023-02-22 \tab 3 \tab 2 \cr
|
|
2023-02-23 \tab 3 \tab 2 \cr
|
|
2023-02-24 \tab 3 \tab 2 \cr
|
|
2023-03-01 \tab 4 \tab 2 \cr
|
|
}
|
|
|
|
|
|
** This marks the start of a new episode, because 8 January 2023 is more than 7 days since the start of the previous episode (1 January 2023). \cr
|
|
*** This marks the start of a new episode, because 21 January 2023 is more than 7 days since the last case in the previous episode (8 January 2023).
|
|
|
|
Either \code{episode_days} or \code{case_free_days} must be provided in the function.
|
|
\subsection{Difference between \code{get_episode()} and \code{is_new_episode()}}{
|
|
|
|
The \code{\link[=get_episode]{get_episode()}} function returns the index number of the episode, so all cases/patients/isolates in the first episode will have the number 1, all cases/patients/isolates in the second episode will have the number 2, etc.
|
|
|
|
The \code{\link[=is_new_episode]{is_new_episode()}} function on the other hand, returns \code{TRUE} for every new \code{\link[=get_episode]{get_episode()}} index.
|
|
|
|
To specify, when setting \code{episode_days = 365} (using method 1 as explained above), this is how the two functions differ:\tabular{cccc}{
|
|
patient \tab date \tab \code{get_episode()} \tab \code{is_new_episode()} \cr
|
|
A \tab 2019-01-01 \tab 1 \tab TRUE \cr
|
|
A \tab 2019-03-01 \tab 1 \tab FALSE \cr
|
|
A \tab 2021-01-01 \tab 2 \tab TRUE \cr
|
|
B \tab 2008-01-01 \tab 1 \tab TRUE \cr
|
|
B \tab 2008-01-01 \tab 1 \tab FALSE \cr
|
|
C \tab 2020-01-01 \tab 1 \tab TRUE \cr
|
|
}
|
|
|
|
}
|
|
|
|
\subsection{Other}{
|
|
|
|
The \code{\link[=first_isolate]{first_isolate()}} function is a wrapper around the \code{\link[=is_new_episode]{is_new_episode()}} function, but is more efficient for data sets containing microorganism codes or names and allows for different isolate selection methods.
|
|
|
|
The \code{dplyr} package is not required for these functions to work, but these episode functions do support \link[dplyr:group_by]{variable grouping} and work conveniently inside \code{dplyr} verbs such as \code{\link[dplyr:filter]{filter()}}, \code{\link[dplyr:mutate]{mutate()}} and \code{\link[dplyr:summarise]{summarise()}}.
|
|
}
|
|
}
|
|
\examples{
|
|
# difference between absolute and relative determination of episodes:
|
|
x <- data.frame(dates = as.Date(c(
|
|
"2021-01-01",
|
|
"2021-01-02",
|
|
"2021-01-05",
|
|
"2021-01-08",
|
|
"2021-02-21",
|
|
"2021-02-22",
|
|
"2021-02-23",
|
|
"2021-02-24",
|
|
"2021-03-01",
|
|
"2021-03-01"
|
|
)))
|
|
x$absolute <- get_episode(x$dates, episode_days = 7)
|
|
x$relative <- get_episode(x$dates, case_free_days = 7)
|
|
x
|
|
|
|
|
|
# `example_isolates` is a data set available in the AMR package.
|
|
# See ?example_isolates
|
|
df <- example_isolates[sample(seq_len(2000), size = 100), ]
|
|
|
|
get_episode(df$date, episode_days = 60) # indices
|
|
is_new_episode(df$date, episode_days = 60) # TRUE/FALSE
|
|
|
|
# filter on results from the third 60-day episode only, using base R
|
|
df[which(get_episode(df$date, 60) == 3), ]
|
|
|
|
# the functions also work for less than a day, e.g. to include one per hour:
|
|
get_episode(
|
|
c(
|
|
Sys.time(),
|
|
Sys.time() + 60 * 60
|
|
),
|
|
episode_days = 1 / 24
|
|
)
|
|
|
|
\donttest{
|
|
if (require("dplyr")) {
|
|
# is_new_episode() can also be used in dplyr verbs to determine patient
|
|
# episodes based on any (combination of) grouping variables:
|
|
df \%>\%
|
|
mutate(condition = sample(
|
|
x = c("A", "B", "C"),
|
|
size = 100,
|
|
replace = TRUE
|
|
)) \%>\%
|
|
group_by(patient, condition) \%>\%
|
|
mutate(new_episode = is_new_episode(date, 365)) \%>\%
|
|
select(patient, date, condition, new_episode) \%>\%
|
|
arrange(patient, condition, date)
|
|
}
|
|
|
|
if (require("dplyr")) {
|
|
df \%>\%
|
|
group_by(ward, patient) \%>\%
|
|
transmute(date,
|
|
patient,
|
|
new_index = get_episode(date, 60),
|
|
new_logical = is_new_episode(date, 60)
|
|
) \%>\%
|
|
arrange(patient, ward, date)
|
|
}
|
|
|
|
if (require("dplyr")) {
|
|
df \%>\%
|
|
group_by(ward) \%>\%
|
|
summarise(
|
|
n_patients = n_distinct(patient),
|
|
n_episodes_365 = sum(is_new_episode(date, episode_days = 365)),
|
|
n_episodes_60 = sum(is_new_episode(date, episode_days = 60)),
|
|
n_episodes_30 = sum(is_new_episode(date, episode_days = 30))
|
|
)
|
|
}
|
|
|
|
# grouping on patients and microorganisms leads to the same
|
|
# results as first_isolate() when using 'episode-based':
|
|
if (require("dplyr")) {
|
|
x <- df \%>\%
|
|
filter_first_isolate(
|
|
include_unknown = TRUE,
|
|
method = "episode-based"
|
|
)
|
|
|
|
y <- df \%>\%
|
|
group_by(patient, mo) \%>\%
|
|
filter(is_new_episode(date, 365)) \%>\%
|
|
ungroup()
|
|
|
|
identical(x, y)
|
|
}
|
|
|
|
# but is_new_episode() has a lot more flexibility than first_isolate(),
|
|
# since you can now group on anything that seems relevant:
|
|
if (require("dplyr")) {
|
|
df \%>\%
|
|
group_by(patient, mo, ward) \%>\%
|
|
mutate(flag_episode = is_new_episode(date, 365)) \%>\%
|
|
select(group_vars(.), flag_episode)
|
|
}
|
|
}
|
|
}
|
|
\seealso{
|
|
\code{\link[=first_isolate]{first_isolate()}}
|
|
}
|