diff --git a/R/epi_df.R b/R/epi_df.R
index a1a5f3bb..abef52c0 100644
--- a/R/epi_df.R
+++ b/R/epi_df.R
@@ -105,8 +105,9 @@ NULL
#' then the current day-time will be used.
#' @param additional_metadata List of additional metadata to attach to the
#' `epi_df` object. The metadata will have `geo_type`, `time_type`, and
-#' `as_of` fields; named entries from the passed list or will be included as
-#' well.
+#' `as_of` fields; named entries from the passed list will be included as
+#' well. If your tibble has additional keys, be sure to specify them as a
+#' character vector in the `other_keys` component of `additional_metadata`.
#' @param ... Additional arguments passed to methods.
#' @return An `epi_df` object.
#'
@@ -117,7 +118,11 @@ new_epi_df = function(x = tibble::tibble(), geo_type, time_type, as_of,
if (!is.data.frame(x)) {
Abort("`x` must be a data frame.")
}
-
+
+ if (!is.list(additional_metadata)) {
+ Abort("`additional_metadata` must be a list type.")
+ }
+
# If geo type is missing, then try to guess it
if (missing(geo_type)) {
geo_type = guess_geo_type(x$geo_value)
@@ -184,8 +189,9 @@ new_epi_df = function(x = tibble::tibble(), geo_type, time_type, as_of,
#' then the current day-time will be used.
#' @param additional_metadata List of additional metadata to attach to the
#' `epi_df` object. The metadata will have `geo_type`, `time_type`, and
-#' `as_of` fields; named entries from the passed list or will be included as
-#' well.
+#' `as_of` fields; named entries from the passed list will be included as
+#' well. If your tibble has additional keys, be sure to specify them as a
+#' character vector in the `other_keys` component of `additional_metadata`.
#' @param ... Additional arguments passed to methods.
#' @return An `epi_df` object.
#'
@@ -230,7 +236,7 @@ new_epi_df = function(x = tibble::tibble(), geo_type, time_type, as_of,
#'
#' ex2 <- ex2_input %>% dplyr::rename(geo_value = state, time_value = reported_date) %>%
#' as_epi_df(geo_type = "state", as_of = "2020-06-03",
-#' additional_metadata = c(other_keys = "pol"))
+#' additional_metadata = list(other_keys = "pol"))
#'
#' attr(ex2,"metadata")
#'
@@ -244,8 +250,13 @@ new_epi_df = function(x = tibble::tibble(), geo_type, time_type, as_of,
#'
#' ex3 <- ex3_input %>%
#' tsibble::as_tsibble() %>% # needed to add the additional metadata
-#' dplyr::mutate(state = rep("MA",6)) %>%
-#' as_epi_df(additional_metadata = c(other_keys = "state"))
+#' # add 2 extra keys
+#' dplyr::mutate(
+#' state = rep("MA",6),
+#' pol = rep(c("blue", "swing", "swing"), each = 2)) %>%
+#' # the 2 extra keys we added have to be specified in the other_keys
+#' # component of additional_metadata.
+#' as_epi_df(additional_metadata = list(other_keys = c("state", "pol")))
#'
#' attr(ex3,"metadata")
as_epi_df = function(x, ...) {
diff --git a/man/as_epi_archive.Rd b/man/as_epi_archive.Rd
index a98798cc..d13ba4d6 100644
--- a/man/as_epi_archive.Rd
+++ b/man/as_epi_archive.Rd
@@ -91,15 +91,11 @@ examples.
}
\details{
This simply a wrapper around the \code{new()} method of the \code{epi_archive}
-class, so for example:
-
-\if{html}{\out{
}}\preformatted{x <- as_epi_archive(df, geo_type = "state", time_type = "day")
-}\if{html}{\out{
}}
-
-would be equivalent to:
+class, so for example:\preformatted{x <- as_epi_archive(df, geo_type = "state", time_type = "day")
+}
-\if{html}{\out{}}\preformatted{x <- epi_archive$new(df, geo_type = "state", time_type = "day")
-}\if{html}{\out{
}}
+would be equivalent to:\preformatted{x <- epi_archive$new(df, geo_type = "state", time_type = "day")
+}
}
\examples{
# Simple ex. with necessary keys
diff --git a/man/as_epi_df.Rd b/man/as_epi_df.Rd
index b5df1302..6d7592e4 100644
--- a/man/as_epi_df.Rd
+++ b/man/as_epi_df.Rd
@@ -39,8 +39,9 @@ then the current day-time will be used.}
\item{additional_metadata}{List of additional metadata to attach to the
\code{epi_df} object. The metadata will have \code{geo_type}, \code{time_type}, and
-\code{as_of} fields; named entries from the passed list or will be included as
-well.}
+\code{as_of} fields; named entries from the passed list will be included as
+well. If your tibble has additional keys, be sure to specify them as a
+character vector in the \code{other_keys} component of \code{additional_metadata}.}
}
\value{
An \code{epi_df} object.
@@ -51,9 +52,9 @@ examples.
}
\section{Methods (by class)}{
\itemize{
-\item \code{as_epi_df(epi_df)}: Simply returns the \code{epi_df} object unchanged.
+\item \code{epi_df}: Simply returns the \code{epi_df} object unchanged.
-\item \code{as_epi_df(tbl_df)}: The input tibble \code{x} must contain the columns
+\item \code{tbl_df}: The input tibble \code{x} must contain the columns
\code{geo_value} and \code{time_value}. All other columns will be preserved as is,
and treated as measured variables. If \code{as_of} is missing, then the function
will try to guess it from an \code{as_of}, \code{issue}, or \code{version} column of \code{x}
@@ -61,14 +62,14 @@ will try to guess it from an \code{as_of}, \code{issue}, or \code{version} colum
(stored in its attributes); if this fails, then the current day-time will
be used.
-\item \code{as_epi_df(data.frame)}: Works analogously to \code{as_epi_df.tbl_df()}.
+\item \code{data.frame}: Works analogously to \code{as_epi_df.tbl_df()}.
-\item \code{as_epi_df(tbl_ts)}: Works analogously to \code{as_epi_df.tbl_df()}, except that
+\item \code{tbl_ts}: Works analogously to \code{as_epi_df.tbl_df()}, except that
the \code{tbl_ts} class is dropped, and any key variables (other than
"geo_value") are added to the metadata of the returned object, under the
\code{other_keys} field.
-
}}
+
\examples{
# Convert a `tsibble` that has county code as an extra key
# Notice that county code should be a character string to preserve any leading zeroes
@@ -109,7 +110,7 @@ print(ex2_input)
ex2 <- ex2_input \%>\% dplyr::rename(geo_value = state, time_value = reported_date) \%>\%
as_epi_df(geo_type = "state", as_of = "2020-06-03",
- additional_metadata = c(other_keys = "pol"))
+ additional_metadata = list(other_keys = "pol"))
attr(ex2,"metadata")
@@ -123,8 +124,13 @@ ex3_input <- jhu_csse_county_level_subset \%>\%
ex3 <- ex3_input \%>\%
tsibble::as_tsibble() \%>\% # needed to add the additional metadata
- dplyr::mutate(state = rep("MA",6)) \%>\%
- as_epi_df(additional_metadata = c(other_keys = "state"))
+ # add 2 extra keys
+ dplyr::mutate(
+ state = rep("MA",6),
+ pol = rep(c("blue", "swing", "swing"), each = 2)) \%>\%
+ # the 2 extra keys we added have to be specified in the other_keys
+ # component of additional_metadata.
+ as_epi_df(additional_metadata = list(other_keys = c("state", "pol")))
attr(ex3,"metadata")
}
diff --git a/man/epi_archive.Rd b/man/epi_archive.Rd
index 026f27e1..0b198eab 100644
--- a/man/epi_archive.Rd
+++ b/man/epi_archive.Rd
@@ -114,18 +114,18 @@ toy_epi_archive
\section{Methods}{
\subsection{Public methods}{
\itemize{
-\item \href{#method-epi_archive-new}{\code{epi_archive$new()}}
-\item \href{#method-epi_archive-print}{\code{epi_archive$print()}}
-\item \href{#method-epi_archive-as_of}{\code{epi_archive$as_of()}}
-\item \href{#method-epi_archive-fill_through_version}{\code{epi_archive$fill_through_version()}}
-\item \href{#method-epi_archive-merge}{\code{epi_archive$merge()}}
-\item \href{#method-epi_archive-slide}{\code{epi_archive$slide()}}
-\item \href{#method-epi_archive-clone}{\code{epi_archive$clone()}}
+\item \href{#method-new}{\code{epi_archive$new()}}
+\item \href{#method-print}{\code{epi_archive$print()}}
+\item \href{#method-as_of}{\code{epi_archive$as_of()}}
+\item \href{#method-fill_through_version}{\code{epi_archive$fill_through_version()}}
+\item \href{#method-merge}{\code{epi_archive$merge()}}
+\item \href{#method-slide}{\code{epi_archive$slide()}}
+\item \href{#method-clone}{\code{epi_archive$clone()}}
}
}
\if{html}{\out{
}}
-\if{html}{\out{}}
-\if{latex}{\out{\hypertarget{method-epi_archive-new}{}}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-new}{}}}
\subsection{Method \code{new()}}{
Creates a new \code{epi_archive} object.
\subsection{Usage}{
@@ -195,8 +195,8 @@ An \code{epi_archive} object.
}
}
\if{html}{\out{
}}
-\if{html}{\out{}}
-\if{latex}{\out{\hypertarget{method-epi_archive-print}{}}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-print}{}}}
\subsection{Method \code{print()}}{
\subsection{Usage}{
\if{html}{\out{}}\preformatted{epi_archive$print()}\if{html}{\out{
}}
@@ -204,8 +204,8 @@ An \code{epi_archive} object.
}
\if{html}{\out{
}}
-\if{html}{\out{}}
-\if{latex}{\out{\hypertarget{method-epi_archive-as_of}{}}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-as_of}{}}}
\subsection{Method \code{as_of()}}{
Generates a snapshot in \code{epi_df} format as of a given version.
See the documentation for the wrapper function \code{\link[=epix_as_of]{epix_as_of()}} for details.
@@ -215,8 +215,8 @@ See the documentation for the wrapper function \code{\link[=epix_as_of]{epix_as_
}
\if{html}{\out{
}}
-\if{html}{\out{}}
-\if{latex}{\out{\hypertarget{method-epi_archive-fill_through_version}{}}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-fill_through_version}{}}}
\subsection{Method \code{fill_through_version()}}{
Fill in unobserved history using requested scheme by mutating
\code{self} and potentially reseating its fields. See
@@ -237,8 +237,8 @@ version, which doesn't mutate the input archive but might alias its fields.
}
}
\if{html}{\out{
}}
-\if{html}{\out{}}
-\if{latex}{\out{\hypertarget{method-epi_archive-merge}{}}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-merge}{}}}
\subsection{Method \code{merge()}}{
Merges another \code{epi_archive} with the current one, mutating the
current one by reseating its \code{DT} and several other fields, but avoiding
@@ -267,8 +267,8 @@ does not alias either archive's \code{DT}.
}
}
\if{html}{\out{
}}
-\if{html}{\out{}}
-\if{latex}{\out{\hypertarget{method-epi_archive-slide}{}}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-slide}{}}}
\subsection{Method \code{slide()}}{
Slides a given function over variables in an \code{epi_archive}
object. See the documentation for the wrapper function \code{\link[=epix_slide]{epix_slide()}} for
@@ -290,8 +290,8 @@ details.
}
\if{html}{\out{
}}
-\if{html}{\out{}}
-\if{latex}{\out{\hypertarget{method-epi_archive-clone}{}}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-clone}{}}}
\subsection{Method \code{clone()}}{
The objects of this class are cloneable with this method.
\subsection{Usage}{
diff --git a/man/epi_slide.Rd b/man/epi_slide.Rd
index 1b620b69..c64bbce1 100644
--- a/man/epi_slide.Rd
+++ b/man/epi_slide.Rd
@@ -107,16 +107,12 @@ incomplete windows) is therefore left up to the user, either through the
specified function or formula \code{f}, or through post-processing.
If \code{f} is missing, then an expression for tidy evaluation can be specified,
-for example, as in:
-
-\if{html}{\out{}}\preformatted{epi_slide(x, cases_7dav = mean(cases), n = 7)
-}\if{html}{\out{
}}
-
-which would be equivalent to:
+for example, as in:\preformatted{epi_slide(x, cases_7dav = mean(cases), n = 7)
+}
-\if{html}{\out{}}\preformatted{epi_slide(x, function(x, ...) mean(x$cases), n = 7,
+which would be equivalent to:\preformatted{epi_slide(x, function(x, ...) mean(x$cases), n = 7,
new_col_name = "cases_7dav")
-}\if{html}{\out{
}}
+}
Thus, to be clear, when the computation is specified via an expression for
tidy evaluation (first example, above), then the name for the new column is
diff --git a/man/epix_as_of.Rd b/man/epix_as_of.Rd
index 4053cd28..6dc72a44 100644
--- a/man/epix_as_of.Rd
+++ b/man/epix_as_of.Rd
@@ -29,15 +29,11 @@ examples.
}
\details{
This is simply a wrapper around the \code{as_of()} method of the
-\code{epi_archive} class, so if \code{x} is an \code{epi_archive} object, then:
-
-\if{html}{\out{}}\preformatted{epix_as_of(x, max_version = v)
-}\if{html}{\out{
}}
-
-is equivalent to:
+\code{epi_archive} class, so if \code{x} is an \code{epi_archive} object, then:\preformatted{epix_as_of(x, max_version = v)
+}
-\if{html}{\out{}}\preformatted{x$as_of(max_version = v)
-}\if{html}{\out{
}}
+is equivalent to:\preformatted{x$as_of(max_version = v)
+}
}
\examples{
# warning message of data latency shown
diff --git a/man/epix_slide.Rd b/man/epix_slide.Rd
index 79e9c1c3..2acae1a1 100644
--- a/man/epix_slide.Rd
+++ b/man/epix_slide.Rd
@@ -115,15 +115,11 @@ should never be used in place of \code{epi_slide()}, and only used when
version-aware sliding is necessary (as it its purpose).
Finally, this is simply a wrapper around the \code{slide()} method of the
-\code{epi_archive} class, so if \code{x} is an \code{epi_archive} object, then:
-
-\if{html}{\out{}}\preformatted{epix_slide(x, new_var = comp(old_var), n = 120)
-}\if{html}{\out{
}}
-
-is equivalent to:
+\code{epi_archive} class, so if \code{x} is an \code{epi_archive} object, then:\preformatted{epix_slide(x, new_var = comp(old_var), n = 120)
+}
-\if{html}{\out{}}\preformatted{x$slide(x, new_var = comp(old_var), n = 120)
-}\if{html}{\out{
}}
+is equivalent to:\preformatted{x$slide(x, new_var = comp(old_var), n = 120)
+}
}
\examples{
# these dates are reference time points for the 3 day average sliding window
diff --git a/man/new_epi_df.Rd b/man/new_epi_df.Rd
index 95f8dc9f..7182c222 100644
--- a/man/new_epi_df.Rd
+++ b/man/new_epi_df.Rd
@@ -32,8 +32,9 @@ then the current day-time will be used.}
\item{additional_metadata}{List of additional metadata to attach to the
\code{epi_df} object. The metadata will have \code{geo_type}, \code{time_type}, and
-\code{as_of} fields; named entries from the passed list or will be included as
-well.}
+\code{as_of} fields; named entries from the passed list will be included as
+well. If your tibble has additional keys, be sure to specify them as a
+character vector in the \code{other_keys} component of \code{additional_metadata}.}
\item{...}{Additional arguments passed to methods.}
}
diff --git a/tests/testthat/test-epi_df.R b/tests/testthat/test-epi_df.R
index 9165ac4d..10b0015e 100644
--- a/tests/testthat/test-epi_df.R
+++ b/tests/testthat/test-epi_df.R
@@ -24,3 +24,18 @@ test_that("new_epi_df works as intended", {
expect_identical(attributes(epi_tib)$metadata$time_type, "day")
expect_true(lubridate::is.POSIXt(attributes(epi_tib)$metadata$as_of))
})
+
+test_that("as_epi_df errors when additional_metadata is not a list", {
+ # This is the 3rd example from as_epi_df
+ ex_input <- jhu_csse_county_level_subset %>%
+ dplyr::filter(time_value > "2021-12-01", state_name == "Massachusetts") %>%
+ dplyr::slice_tail(n = 6) %>%
+ tsibble::as_tsibble() %>%
+ dplyr::mutate(
+ state = rep("MA",6),
+ pol = rep(c("blue", "swing", "swing"), each = 2))
+
+ expect_error(
+ as_epi_df(ex_input, additional_metadata = c(other_keys = "state", "pol")),
+ "`additional_metadata` must be a list type.")
+})
\ No newline at end of file
diff --git a/tests/testthat/test-methods-epi_df.R b/tests/testthat/test-methods-epi_df.R
index cc6116d8..c03b49ec 100644
--- a/tests/testthat/test-methods-epi_df.R
+++ b/tests/testthat/test-methods-epi_df.R
@@ -8,7 +8,7 @@ toy_epi_df <- tibble::tibble(
), times = 2),
geo_value = rep(c("ca", "hi"), each = 5),
indicator_var = as.factor(rep(1:2, times = 5)),
-) %>% as_epi_df(additional_metadata = c(other_keys = "indicator_var"))
+) %>% as_epi_df(additional_metadata = list(other_keys = "indicator_var"))
att_toy = attr(toy_epi_df, "metadata")
diff --git a/vignettes/epiprocess.Rmd b/vignettes/epiprocess.Rmd
index 379423b0..2dc2266b 100644
--- a/vignettes/epiprocess.Rmd
+++ b/vignettes/epiprocess.Rmd
@@ -180,7 +180,7 @@ head(ex2)
ex2 <- ex2 %>% rename(geo_value = state, time_value = reported_date) %>%
as_epi_df(geo_type = "state", as_of = "2020-06-03",
- additional_metadata = c(other_keys = "pol"))
+ additional_metadata = list(other_keys = "pol"))
attr(ex2,"metadata")
```
@@ -200,17 +200,21 @@ ex3 <- jhu_csse_county_level_subset %>%
attr(ex3,"metadata") # geo_type is county currently
```
-Now we add state (MA) as a new column and a key to the metadata. Reminder that lower case state name abbreviations are what we would expect if this were a `geo_value` column.
-```{r}
+Now we add `state` (MA) and `pol` as new columns to the data and as new keys to the metadata. Reminder that lower case state name abbreviations are what we would expect if this were a `geo_value` column.
+```{r}
ex3 <- ex3 %>%
as_tibble() %>% # needed to add the additional metadata
- mutate(state = rep(tolower("MA"),6)) %>%
- as_epi_df(additional_metadata = c(other_keys = "state"))
+ mutate(
+ state = rep(tolower("MA"),6),
+ pol = rep(c("blue", "swing", "swing"), each = 2)) %>%
+ as_epi_df(additional_metadata = list(other_keys = c("state", "pol")))
attr(ex3,"metadata")
```
+Note that the two additional keys we added, `state` and `pol`, are specified as a character vector in the `other_keys` component of the `additional_metadata` list. They must be specified in this manner so that downstream actions on the `epi_df`, like model fitting and prediction, can recognize and use these keys.
+
Currently `other_keys` metadata in `epi_df` doesn't impact `epi_slide()`, contrary to `other_keys` in `as_epi_archive` which affects how the update data is interpreted.
## Working with `epi_df` objects downstream