diff --git a/DESCRIPTION b/DESCRIPTION index 30c5d1a..57a5e0d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: LightLogR Title: Process Data from Wearable Light Loggers and Optical Radiation Dosimeters -Version: 0.10.1 +Version: 0.10.2 Authors@R: c( person("Johannes", "Zauner", email = "johannes.zauner@tum.de", role = c("aut", "cre"), diff --git a/NEWS.md b/NEWS.md index ec10345..de58f8d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# LightLogR 0.10.2 + +* `add_states()` no longer creates duplicate observations at identical start/endpoints. The default behavior is now that the `start` is inclusive and `end` is exclusive. Adjust the new `bounds` argument for more options. + # LightLogR 0.10.1 * `extract_metric()` give more helpful error messages when using a base dataset without start/end columns. diff --git a/R/add_states.R b/R/add_states.R index 6a171aa..b3308e2 100644 --- a/R/add_states.R +++ b/R/add_states.R @@ -36,6 +36,10 @@ #' will be forced to the same time zone as the `dataset` using #' [lubridate::force_tz()]. If `FALSE` (default), the start and end times of #' the `States.dataset` will be used as is. +#' @param bounds How to treat the edge case, when a state start or endpoint +#' falls onto a data point. See [dplyr::join_by()] for details on the bounds +#' argument (Join types > Overlap joins > between). Basically `[` or `]` +#' signal an inclusive joint, whereas `(` or `)` signal exclusivity. #' #' @returns a modified `dataset` with the states added. The states are added as #' new columns to the `dataset`. The columns are named after the columns in @@ -65,6 +69,7 @@ add_states <- function(dataset, start.colname = start, end.colname = end, force.tz = FALSE, + bounds = c("[)", "[]", "(]", "()"), leave.out = c("duration", "epoch") ){ # Initial Checks ---------------------------------------------------------- @@ -75,6 +80,8 @@ add_states <- function(dataset, "States.dataset is not a dataframe" = is.data.frame(States.dataset) ) + bounds <- rlang::arg_match(bounds) + # Check if Datetime.colname is part of the dataset Datetime.colname.defused <- colname.defused({{ Datetime.colname }}) if (!Datetime.colname.defused %in% names(dataset)) { @@ -171,8 +178,12 @@ add_states <- function(dataset, by = dplyr::join_by( !!!groups, - {{ Datetime.colname }} >= {{ start.colname}}, - {{ Datetime.colname }} <= {{ end.colname }} + dplyr::between({{ Datetime.colname }}, + {{ start.colname}}, + {{ end.colname }}, + bounds = !!bounds) + # {{ Datetime.colname }} >= {{ start.colname}}, + # {{ Datetime.colname }} <= {{ end.colname }} ) ) |> dplyr::select(-{{ start.colname}}, -{{ end.colname }}) diff --git a/man/add_states.Rd b/man/add_states.Rd index 89741bf..370a9ed 100644 --- a/man/add_states.Rd +++ b/man/add_states.Rd @@ -11,6 +11,7 @@ add_states( start.colname = start, end.colname = end, force.tz = FALSE, + bounds = c("[)", "[]", "(]", "()"), leave.out = c("duration", "epoch") ) } @@ -35,6 +36,11 @@ will be forced to the same time zone as the \code{dataset} using \code{\link[lubridate:force_tz]{lubridate::force_tz()}}. If \code{FALSE} (default), the start and end times of the \code{States.dataset} will be used as is.} +\item{bounds}{How to treat the edge case, when a state start or endpoint +falls onto a data point. See \code{\link[dplyr:join_by]{dplyr::join_by()}} for details on the bounds +argument (Join types > Overlap joins > between). Basically \code{[} or \verb{]} +signal an inclusive joint, whereas \code{(} or \verb{)} signal exclusivity.} + \item{leave.out}{A character vector of columns that should not be carried over to the \code{dataset}} } diff --git a/man/import_Dataset.Rd b/man/import_Dataset.Rd index b3a23e0..d320f1a 100644 --- a/man/import_Dataset.Rd +++ b/man/import_Dataset.Rd @@ -321,7 +321,6 @@ such as the intervals between measurements or the start and end dates. \if{html}{\out{