diff --git a/NAMESPACE b/NAMESPACE index 2fa77d9..d3bd17c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,18 +4,23 @@ export("%>%") export(Brown.check) export(Brown.rec) export(Brown2reference) +export(Datetime_breaks) +export(Datetime_limits) export(aggregate_Datetime) +export(count.difftime) export(create_Time.data) export(cut_Datetime) export(data2reference) export(dominant_epoch) export(filter_Date) export(filter_Datetime) +export(filter_Datetime_multiple) export(filter_Time) export(gap_finder) export(gap_handler) export(gapless_Datetimes) export(gg_day) +export(gg_days) export(gg_overview) export(import) export(import.Dataset) diff --git a/NEWS.md b/NEWS.md index 383ca0c..71ea700 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,11 @@ # LightLogR 0.2.1.9000 +* Exports the up to now internal function `count.difftime()` that is the basis for `dominant_epoch()`. But whereas the latter gets only the most common epoch, `count.difftime()` returns a table with the counts of all epochs. This is useful in conjunction with `gap_finder()`, to check the distribution of data intervals. + +* Added the `gg_days()` function to visualize multiple days of data in a single plot. Alongside come two helper functions, `Datetime_limits()` and `Datetime_breaks()`, to set the limits and breaks of the x-axis. + +* Added the `filter_Datetime_multiple()` function to filter for multiple Datetime ranges depending on certain conditions, e.g. different filter cutoffs for different participants. It wraps around `filter_Datetime()` or `filter_Date()`. + * Reworked the internals of the light logger data import functions. They now use a more straightforward function factory approach. For users the only visible change it that device specific functions now have the form `import$device()` instead of the old `import.device()`. * Added the `symlog_trans()` function from a [post on stack overflow](https://stackoverflow.com/a/14674703). This function leads to a better visualization of light logger data, as a logarithmic transformation is necessary, but values of 0 are common. The function was integrated as a default for `gg_day()` and will likely be the basis of upcoming visualization functions. diff --git a/R/aaa.r b/R/aaa.r index 14e55c2..e5f6add 100644 --- a/R/aaa.r +++ b/R/aaa.r @@ -1,4 +1,4 @@ -Time <- mEDI <- Time.data <- Datetime <- timestamp <- tz <- Day.data <- `DATE/TIME` <- n <- Datetime.rounded <- id <- sleep.colname.string <- file.name <- Interval <- original.datapoints.fleeting <- MEDI <- State.Brown <- Reference <- Reference.check <- Id <- Start.date.shift <- data <- Shift <- `MELANOPIC EDI` <- State <- group <- End <- Start <- Quant.x <- Quant.y <- is.implicit <- group.indices <- Id2 <- gap.id <- start <- end <- path <- auto.id <- n_max <- manual.id <- NULL +Time <- mEDI <- Time.data <- Datetime <- timestamp <- tz <- Day.data <- `DATE/TIME` <- n <- Datetime.rounded <- id <- sleep.colname.string <- file.name <- Interval <- original.datapoints.fleeting <- MEDI <- State.Brown <- Reference <- Reference.check <- Id <- Start.date.shift <- data <- Shift <- `MELANOPIC EDI` <- State <- group <- End <- Start <- Quant.x <- Quant.y <- is.implicit <- group.indices <- Id2 <- gap.id <- start <- end <- path <- auto.id <- n_max <- manual.id <- silent <- NULL empty_function <- function() { rsconnect::accountInfo() diff --git a/R/filter_Datetime.R b/R/filter_Datetime.R index 496dea6..f599803 100644 --- a/R/filter_Datetime.R +++ b/R/filter_Datetime.R @@ -32,6 +32,7 @@ #' is FALSE). This is useful, e.g., when the first observation in the dataset #' is slightly after midnight. If TRUE, it will count the length from midnight #' on to avoid empty days in plotting with [gg_day()]. +#' @param only_Id An expression of `ids` where the filtering should be applied to. If `NULL` (the default), the filtering will be applied to all `ids`. Based on the this expression, the dataset will be split in two and only where the given expression evaluates to `TRUE`, will the filtering take place. Afterwards both sets are recombined and sorted by `Datetime`. #' #' @return a `data.frame` object identical to `dataset` but with only the #' specified Dates/Times. @@ -86,12 +87,15 @@ filter_Datetime <- function(dataset, length = NULL, full.day = FALSE, tz = NULL, + only_Id = NULL, filter.expr = NULL) { # Initial Checks ---------------------------------------------------------- filter.expr <- rlang::enexpr(filter.expr) + only_Id <- rlang::enexpr(only_Id) + Datetime.colname.defused <- rlang::enexpr(Datetime.colname) %>% rlang::as_string() #timezone @@ -119,6 +123,16 @@ filter_Datetime <- function(dataset, # Manipulation ---------------------------------------------------------- + #split the dataset in two parts, based on the only_Id expression + if(!is.null(only_Id)) { + dataset_unfiltered <- + dataset %>% + dplyr::filter(!(!!only_Id), .preserve = TRUE) + dataset <- + dataset %>% + dplyr::filter(!!only_Id, .preserve = TRUE) + } + #calculate starting time if length and end are given if(is.null(start) & !is.null(length) & !is.null(end)) { start <- lubridate::as_datetime(end, tz = tz) - length @@ -155,7 +169,10 @@ filter_Datetime <- function(dataset, } # Return -------------------------------------------------------------- - dataset + if(!is.null(only_Id)) { + dplyr::bind_rows(dataset, dataset_unfiltered) %>% + dplyr::arrange({{ Datetime.colname }}, .by_group = TRUE) + } else dataset } @@ -184,4 +201,44 @@ filter_Date <- function(..., filter_Datetime(..., start = start, end = end) +} + +# multiple filter_Date ------------------------------------------------------------- + +#' Filter multiple times based on a list of arguments. +#' +#' [filter_Datetime_multiple()] is a wrapper around [filter_Datetime()] or +#' [filter_Date()] that allows the cumulative filtering of `Datetimes` based on +#' varying filter conditions. It is most useful in conjunction with the +#' `only_Id` argument, e.g., to selectively cut off dates depending on +#' participants (see examples) +#' +#' @param dataset A light logger dataset +#' @param arguments A list of arguments to be passed to [filter_Datetime()] or +#' [filter_Date()]. each list entry must itself be a list of arguments, e.g, +#' `list(start = "2021-01-01", only_Id = quote(Id == 216))`. Expressions have +#' to be quoted with [quote()] or [rlang::expr()]. +#' @param filter_function The function to be used for filtering, either +#' `filter_Datetime` (the default) or `filter_Date` +#' +#' @return A dataframe with the filtered data +#' @export +#' +#' @examples +#' arguments <- list( +#' list(start = "2023-08-17", only_Id = quote(Source == "Participant")), +#' list(end = "2023-08-17", only_Id = quote(Source == "Environment"))) +#' #compare the unfiltered dataset +#' sample.data.environment %>% gg_overview(Id.colname = Source) +#' #compare the unfiltered dataset +#' sample.data.environment %>% +#' filter_Datetime_multiple(arguments = arguments, filter_Date) %>% +#' gg_overview(Id.colname = Source) +filter_Datetime_multiple <- function(dataset, + arguments, + filter_function = filter_Datetime) { + + purrr::reduce(arguments, function(dataset, params) { + do.call({{ filter_function }}, c(list(dataset = dataset), params)) + }, .init = dataset) } \ No newline at end of file diff --git a/R/gg_day.r b/R/gg_day.r index 5e39692..29fe019 100644 --- a/R/gg_day.r +++ b/R/gg_day.r @@ -1,9 +1,9 @@ -#' Create a simple plot of light logger data, facetted by Day +#' Create a simple Time-of-Day plot of light logger data, faceted by Date #' -#' `gg_day` will create a simple ggplot for every data in a dataset. The result -#' can further be manipulated like any ggplot. This will be sensible to refine -#' styling or guides. +#' [gg_day()] will create a simple ggplot for every data in a dataset. The +#' result can further be manipulated like any ggplot. This will be sensible to +#' refine styling or guides. #' #' Besides plotting, the function creates two new variables from the given #' `Datetime`: @@ -11,8 +11,12 @@ #' * `Time.data` is an `hms` created with [hms::as_hms()] that is used for the x.axis #' #' The default scaling of the y-axis is a `symlog` scale, which is a logarithmic -#' scale that only starts scaling after a given threshold (default = 0). This enables values of 0 in the plot, which are common in light logger data, and even enables negative values, which might be sensible for non-light data. See [symlog_trans()] for details on tweaking this scale. The scale can also be changed to a normal or logarithmic scale - see the y.scale argument for more. -#' +#' scale that only starts scaling after a given threshold (default = 0). This +#' enables values of 0 in the plot, which are common in light logger data, and +#' even enables negative values, which might be sensible for non-light data. See +#' [symlog_trans()] for details on tweaking this scale. The scale can also be +#' changed to a normal or logarithmic scale - see the y.scale argument for more. +#' #' @param dataset A light logger dataset. Expects a `dataframe`. If not imported #' by [LightLogR], take care to choose a sensible variable for the `x.axis.`. #' @param x.axis,y.axis column name that contains the datetime (x, defaults to @@ -31,20 +35,20 @@ #' @param start.date,end.date Choose an optional start or end date within your #' `dataset`. Expects a `date`, which can also be a `character` that is #' interpretable as a date, e.g., `"2023-06-03"`. If you need a Datetime or -#' want to cut specific times of each day, use the [filter_Datetime] function. -#' Defaults to `NULL`, which means that the plot starts/ends with the -#' earliest/latest date within the `dataset`. +#' want to cut specific times of each day, use the [filter_Datetime()] +#' function. Defaults to `NULL`, which means that the plot starts/ends with +#' the earliest/latest date within the `dataset`. #' @param scales For [ggplot2::facet_wrap()], should scales be "fixed", "free" #' or free in one dimension ("free_y" is the default). Expects a `character`. -#' @param y.scale How should the y-axis be scaled? -#' * Defaults to `"symlog"`, which is a logarithmic scale that can also handle negative values. +#' @param y.scale How should the y-axis be scaled? +#' * Defaults to `"symlog"`, which is a logarithmic scale that can also handle negative values. #' * `"log10"` would be a straight logarithmic scale, but cannot handle negative values. #' * `"identity"` does nothing (continuous scaling). #' * a transforming function, such as [symlog_trans()] or [scales::identity_trans()], which allow for more control. -#' @param col optional column name that defines separate sets and colors them. -#' Expects anything that works with the layer data [ggplot2::aes()]. The -#' default color palette can be overwritten outside the function (see -#' examples). +#' @param aes_col,aes_fill optional arguments that define separate sets and +#' colors or fills them. Expects anything that works with the layer data +#' [ggplot2::aes()]. The default color palette can be overwritten outside the +#' function (see examples). #' @param x.axis.breaks,y.axis.breaks Where should breaks occur on the x and #' y.axis? Expects a `numeric vector` with all the breaks. If you want to #' activate the default behaviour of [ggplot2], you need to put in @@ -52,17 +56,22 @@ #' @param y.scale.sc `logical` for whether scientific notation shall be used. #' Defaults to `FALSE`. #' @param geom What geom should be used for visualization? Expects a `character` -#' * `"point"` for [ggplot2::geom_point()] (the default) +#' * `"point"` for [ggplot2::geom_point()] #' * `"line"` for [ggplot2::geom_line()] -#' * as the value is just input into the `geom_` function from [ggplot2], other variants might work as well, but are not tested. +#' * `"ribbon"` for [ggplot2::geom_ribbon()] +#' * as the value is just input into the `geom_` function from [ggplot2], other variants work as well, but are not extensively tested. #' @param group Optional column name that defines separate sets. Useful for #' certain geoms like `boxplot`.Expects anything that works with the layer #' data [ggplot2::aes()] #' @param ... Other options that get passed to the main geom function. Can be -#' used to adjust to adjust size or linetype. +#' used to adjust to adjust size, linewidth, or linetype. #' @param interactive Should the plot be interactive? Expects a `logical`. #' Defaults to `FALSE`. -#' @param facetting Should an automated facet by day be applie? Default is `TRUE` and uses the `Day.data` variable that the function also creates if not present. +#' @param facetting Should an automated facet by day be applied? Default is +#' `TRUE` and uses the `Day.data` variable that the function also creates if +#' not present. +#' @param jco_color Should the [ggsci::scale_color_jco()] color palette be used? +#' Defaults to `TRUE`. #' #' @return A ggplot object #' @export @@ -76,7 +85,7 @@ #' x.axis = Datetime, #' y.axis = `MELANOPIC EDI`, #' y.axis.label = "mEDI (lx)", -#' col = Source) +#' aes_col = Source) #' plot #' #' #you can easily overwrite the color scale afterwards @@ -90,7 +99,8 @@ gg_day <- function(dataset, end.date = NULL, x.axis = Datetime, y.axis = MEDI, - col = NULL, + aes_col = NULL, + aes_fill = NULL, group = NULL, geom = "point", scales = "fixed", @@ -105,21 +115,20 @@ gg_day <- function(dataset, subtitle = NULL, interactive = FALSE, facetting = TRUE, + jco_color = TRUE, ...) { # Initial Checks ---------------------------------------------------------- - x <- rlang::enexpr(x.axis) + x <- rlang::enexpr(x.axis) y <- rlang::enexpr(y.axis) - axis_columns <- (purrr::map_chr(c(x,y), rlang::as_string)) + axis_columns <- (purrr::map_chr(c(x,y), deparse1)) stopifnot( "The given dataset is not a dataframe" = is.data.frame(dataset), "The given column for X is not in the Dataset. If you did not specify X, you are working with data not originating from LightLogR. Please specify an appropriate Datetime column" = rlang::as_string(x) %in% names(dataset), "The given column for X is not a Datetime" = lubridate::is.POSIXct(dataset[[rlang::as_string(x)]]), - "The given column for Y is not in the Dataset" = - rlang::as_string(y) %in% names(dataset), "scales must be one of `fixed`, `free_x`, `free_y`, or `free`" = scales %in% c("free_y", "free_x", "fixed", "free"), "format.day must be a character. Please make shure it is of type `base::strptime`" = @@ -139,7 +148,10 @@ gg_day <- function(dataset, ribbon <- list( ggplot2::geom_ribbon( - ggplot2::aes(ymin = 0, ymax = !!y), + ggplot2::aes(ymin = 0, ymax = !!y, + group = {{ group }}, + col = {{ aes_col }}, + fill = {{ aes_fill }}), outline.type = "upper", ... ) @@ -147,6 +159,15 @@ gg_day <- function(dataset, } + #jco color palette + jco_color_scheme <- list() + if(jco_color) { + jco_color_scheme <- + list( + ggsci::scale_color_jco() + ) + } + #filter by start and end date if(!is.null(start.date)) { dataset <- @@ -190,11 +211,12 @@ gg_day <- function(dataset, eval(geom_function_expr)( ggplot2::aes( group = {{ group }}, - col = {{ col }}, + col = {{ aes_col }}, + fill = {{ aes_fill }}, ), ...) + ribbon + # Scales -------------------------------------------------------------- - ggsci::scale_color_jco()+ + jco_color_scheme+ ggplot2::scale_x_time(breaks = x.axis.breaks, labels = scales::label_time(format = "%H:%M")) + ggplot2::scale_y_continuous( diff --git a/R/gg_days.R b/R/gg_days.R new file mode 100644 index 0000000..6251e3c --- /dev/null +++ b/R/gg_days.R @@ -0,0 +1,179 @@ +#' Create a simple datetime plot of light logger data, faceted by group +#' +#' [gg_days()] will create a simple ggplot along the timeline. The result can +#' further be manipulated like any ggplot. This will be sensible to refine +#' styling or guides. Through the `x.axis.limits` arguments, the plot can be +#' much refined to align several groups of differing datetime ranges. It uses +#' the [Datetime_limits()] function to calculate the limits of the x-axis. +#' Another notable functions that are used are [Datetime_breaks()] to calculate +#' the breaks of the x-axis. +#' +#' The default scaling of the y-axis is a `symlog` scale, which is a logarithmic +#' scale that only starts scaling after a given threshold (default = 0). This +#' enables values of 0 in the plot, which are common in light logger data, and +#' even enables negative values, which might be sensible for non-light data. See +#' [symlog_trans()] for details on tweaking this scale. The scale can also be +#' changed to a normal or logarithmic scale - see the y.scale argument for more. +#' @inheritParams gg_day +#' @param aes_col,aes_fill optional input that defines separate sets and colors +#' or fills them. Expects anything that works with the layer data +#' [ggplot2::aes()]. +#' @param y.axis.breaks Where should breaks occur on the y.axis? Expects a +#' `numeric vector` with all the breaks or a function that calculates them +#' based on the limits. If you want to activate the default behaviour of +#' [ggplot2], you need to put in [ggplot2::waiver()]. +#' @param x.axis.breaks The (major) breaks of the x-axis. Defaults to +#' [Datetime_breaks()]. The function has several options for adjustment. The +#' default setting place a major break every 12 hours, starting at 12:00 of +#' the first day. +#' @param x.axis.limits The limits of the x-axis. Defaults to +#' [Datetime_limits()]. Can and should be adjusted to shift the x-axis to +#' align different groups of data. +#' @param x.axis.format The format of the x-axis labels. Defaults to `"%a %D"`, +#' which is the weekday and date. See [base::strptime()] for more options. +#' @param facetting Should an automated facet by grouping be applied? Default is +#' `TRUE`. +#' +#' @return A ggplot object +#' @export +#' +#' @examples +#' dataset <- +#' sample.data.environment %>% +#' dplyr::group_by(Source) %>% +#' aggregate_Datetime(unit = "5 mins") +#' +#' dataset %>% gg_days(y.axis = `MELANOPIC EDI`) +#' #restrict the x-axis to 3 days +#' dataset %>% +#' gg_days( +#' y.axis = `MELANOPIC EDI`, +#' x.axis.limits = \(x) Datetime_limits(x, length = lubridate::ddays(3)) +#' ) +gg_days <- function(dataset, + x.axis = Datetime, + y.axis = MEDI, + aes_col = NULL, + aes_fill = NULL, + group = NULL, + geom = "line", + scales = "free_x", + x.axis.breaks = Datetime_breaks, + y.axis.breaks = c(-10^(5:0), 0, 10^(0:5)), + y.scale = "symlog", + y.scale.sc = FALSE, + x.axis.label = "Datetime", + y.axis.label = "Illuminance (lx, MEDI)", + x.axis.limits = Datetime_limits, + x.axis.format = "%a %D", + title = NULL, + subtitle = NULL, + interactive = FALSE, + facetting = TRUE, + ...) { + + # Initial Checks ---------------------------------------------------------- + + x <- rlang::enexpr(x.axis) + y <- rlang::enexpr(y.axis) + axis_columns <- (purrr::map_chr(c(x,y), deparse1)) + stopifnot( + "The given dataset is not a dataframe" = is.data.frame(dataset), + "The given column for X is not in the Dataset. If you did not specify X, you are working with data not originating from LightLogR. Please specify an appropriate Datetime column" = + rlang::as_string(x) %in% names(dataset), + "The given column for X is not a Datetime" = + lubridate::is.POSIXct(dataset[[rlang::as_string(x)]]), + "scales must be one of `fixed`, `free_x`, `free_y`, or `free`" = + scales %in% c("free_y", "free_x", "fixed", "free"), + "The X axis label must be a string" = is.character(x.axis.label), + "The Y axis label must be a string" = is.character(y.axis.label), + "interactive must be a logical" = is.logical(interactive) + ) + + # Data Preparation -------------------------------------------------------- + + #special case for geom = "ribbon" + ribbon <- list() + if(geom == "ribbon") { + geom <- "blank" + ribbon <- + rlang::inject(list( + ggplot2::geom_ribbon( + ggplot2::aes( + ymin = 0, ymax = !!y, + group = {{ group }}, + fill = {{ aes_fill }}, + col = {{ aes_col }} + ), + outline.type = "upper", + ... + ) + )) + + } + + #grouping_vars + grouping_var <- dplyr::group_vars(dataset) + + #give the user the chance to use whatever geom they want + geom_function_expr <- rlang::parse_expr(paste0("ggplot2::geom_", geom)) + + # Plot Creation ----------------------------------------------------------- + + Plot <- + dataset %>% + #basic setup + ggplot2::ggplot(ggplot2::aes(x=!!x, y = !!y)) + + eval(geom_function_expr)( + ggplot2::aes( + group = {{ group }}, + fill = {{ aes_fill }}, + col = {{ aes_col }}, + ), ...) + + ribbon + + # Scales -------------------------------------------------------------- + ggplot2::scale_y_continuous( + trans = y.scale, + breaks = y.axis.breaks, + labels = function(x) format(x, scientific = y.scale.sc, big.mark = " ") + )+ + ggplot2::scale_x_datetime( + breaks = x.axis.breaks, + date_minor_breaks = "24 hours", + date_labels = x.axis.format, + limits = x.axis.limits, + expand = c(0,0) + )+ + # Styling -------------------------------------------------------------- + ggplot2::labs( + y= y.axis.label, + x= x.axis.label, + title = title, + subtitle = subtitle + )+ + cowplot::theme_cowplot()+ + ggplot2::theme( + plot.title.position = "plot", + panel.grid.major.y = ggplot2::element_line("grey98"), + panel.grid.major.x = + ggplot2::element_line(color = "grey80", linetype = 2, linewidth = 0.25), + panel.grid.minor.x = + ggplot2::element_line(color = "grey80", linewidth = 0.25), + strip.text.y = ggplot2::element_text(face = "bold",), + strip.placement = "outside" + ) + + # Facetting ------------------------------------------------------------ + if(facetting) { + ggplot2::facet_wrap( + grouping_var, + ncol=1, + scales = scales, + strip.position = "left") + } + + # Return -------------------------------------------------------------- + if(interactive) { + Plot %>% plotly::ggplotly() + } + else Plot +} diff --git a/R/gg_overview.R b/R/gg_overview.R index 1c97399..50ef01f 100644 --- a/R/gg_overview.R +++ b/R/gg_overview.R @@ -109,6 +109,7 @@ gg_overview <- function(dataset, #general information ggplot2::labs(x = "Datetime")+ #theming and styling + ggplot2::scale_x_datetime()+ cowplot::theme_cowplot()+ ggplot2::theme( panel.grid.major = ggplot2::element_line(colour = "grey98"), diff --git a/R/helper.R b/R/helper.R index 804ca4d..9369a79 100644 --- a/R/helper.R +++ b/R/helper.R @@ -38,14 +38,36 @@ is.all.scalar <- function(...) { purrr::every(\(x) length(x) == 1) } -#counts the different time differences per group (in a grouped dataset) +#' Counts the Time differences (epochs) per group (in a grouped dataset) +#' +#' @inheritParams cut_Datetime +#' +#' @return a `tibble` with the number of occurences of each time difference per +#' group +#' @export +#' +#' @examples +#' #get a dataset with irregular intervals +#' filepath <- system.file("extdata/sample_data_LYS.csv", package = "LightLogR") +#' dataset <- import$LYS(filepath) +#' +#' #count.difftime returns the number of occurences of each time difference +#' #and is more comprehensive in terms of a summary than `gap_finder` or +#' #`dominant_epoch` +#' count.difftime(dataset) +#' dominant_epoch(dataset) +#' gap_finder(dataset) +#' +#' #irregular data can be regularized with `aggregate_Datetime` +#' dataset %>% aggregate_Datetime(unit = "15 secs") %>% count.difftime() + count.difftime <- function(dataset, Datetime.colname = Datetime) { dataset %>% dplyr::mutate( difftime = c(NA, diff({{Datetime.colname}}) %>% lubridate::as.duration()) ) %>% tidyr::drop_na(difftime) %>% - dplyr::count(difftime, sort = TRUE) + dplyr::count(difftime = difftime %>% lubridate::as.duration(), sort = TRUE) } #calculate the nth Quantile of time differences per group (in a grouped dataset) diff --git a/R/import_LL.R b/R/import_LL.R index 28a1e8f..eee5a14 100644 --- a/R/import_LL.R +++ b/R/import_LL.R @@ -47,7 +47,7 @@ #' by the `device.ext` spec to access the sample file): #' * `"ActLumus"` (ActLumus.txt) #' * `"LYS"` (LYS.csv) -#' * `"Actiwatch_Spectrum"` (Actiwatch.csv) *Note: as the `locale` argument use `readr::locale(encoding="latin1")` . This is due to the fact that the German Actiwatch software from which this sample file was taken, uses a different encoding than UTF-8.* +#' * `"Actiwatch_Spectrum"` (Actiwatch.csv) **Special Argument: `column_names`** A character vector containing column names in the order in which they appear in the file. This is necessary to find the starting point of actual data.*Note: as the `locale` argument use `readr::locale(encoding="latin1")` . This is due to the fact that the German Actiwatch software from which this sample file was taken, uses a different encoding than UTF-8.* #' @importFrom rlang := #' @return Tibble/Dataframe with a POSIXct column for the datetime #' @export @@ -124,6 +124,7 @@ imports <- function(device, auto.id = ".*", manual.id = NULL, locale = readr::default_locale(), + silent = FALSE, ... = ), #function expression @@ -169,7 +170,7 @@ imports <- function(device, dplyr::arrange(Datetime, .by_group = TRUE) #give info about the file - import.info(tmp, !!device, tz, !!ID.colname) + if(!silent) import.info(tmp, !!device, tz, !!ID.colname) #return the file tmp diff --git a/R/symlog_trans.R b/R/symlog_trans.R index f69337d..b04a9e5 100644 --- a/R/symlog_trans.R +++ b/R/symlog_trans.R @@ -23,13 +23,13 @@ #' .default = `MELANOPIC EDI`)) #' #basic application where transformation, breaks and labels are set manually #' dataset %>% -#' gg_day(col = Source) + +#' gg_day(aes_col = Source) + #' ggplot2::scale_y_continuous( #' trans = "symlog") #' #' #the same plot, but with breaks and labels set manually #' dataset %>% -#' gg_day(col = Source) + +#' gg_day(aes_col = Source) + #' ggplot2::scale_y_continuous( #' trans = "symlog", #' breaks = c(-10^(5:0), 0, 10^(0:5)), @@ -38,7 +38,7 @@ #' #setting individual arguments of the symlog function manually allows #' #e.g., to emphasize values smaller than 1 #' dataset %>% -#' gg_day(col = Source) + +#' gg_day(aes_col = Source) + #' ggplot2::scale_y_continuous( #' trans = symlog_trans(thr = 0.01), #' breaks = c(-10^(5:-1), 0, 10^(-1:5)), diff --git a/R/visualize_helper.R b/R/visualize_helper.R new file mode 100644 index 0000000..5cd4bff --- /dev/null +++ b/R/visualize_helper.R @@ -0,0 +1,81 @@ +#' Create a (shifted) sequence of Datetimes for axis breaks +#' +#' Take a vector of Datetimes and create a sequence of Datetimes with a given +#' shift and interval. This is a helper function to create breaks for plotting, +#' e.g. in [gg_days()], and is best used in conjunction with +#' [Datetime_limits()]. The function is a thin wrapper around [seq()]. +#' +#' @param x a vector of `Datetimes` +#' @param shift a `numeric` giving the number of `duration` object, e.g. +#' `lubridate::duration(12, "hours")` +#' @param by a `character` scalar giving the unit of the interval in +#' [base::seq()] +#' +#' @return a `vector` of `Datetimes` +#' @export +#' +#' @examples +#' dataset <- c("2023-08-15", "2023-08-20") +#' Datetime_breaks(dataset) +#' Datetime_breaks(dataset, shift = 0) +#' Datetime_breaks(dataset, by = "12 hours") + +Datetime_breaks <- function(x, + shift = lubridate::duration(12, "hours"), + by = "1 day") { + x <- lubridate::as_datetime(x) + (min(x) + shift) %>% + seq(max(x), by = by) +} + +#' Find or set sensible limits for Datetime axis +#' +#' Take a vector of `Datetimes` and return the start of the first and end of the +#' last day of data. The `start` and the `length` can be adjusted by +#' `durations`, like [lubridate::ddays()]. It is used in the [gg_days()] +#' function to return a sensible axis. This function is a thin wrapper around +#' [lubridate::floor_date()] and [lubridate::ceiling_date()]. +#' +#' @param x a vector of `Datetimes` +#' @param start optional `duration` object, e.g. `lubridate::ddays(1)` that +#' shifts the start of the `Datetime` vector by this amount. +#' @param length optional `duration` object, e.g. `lubridate::ddays(7)` that +#' shifts the end of the `Datetime` vector by this amount from the (adjusted) +#' start. +#' @param unit a `character` scalar giving the unit of rounding in +#' [lubridate::floor_date()] and [lubridate::ceiling_date()] +#' @param ... other arguments passed to [lubridate::floor_date()] and +#' [lubridate::ceiling_date()] +#' +#' @return a 2 item `vector` of `Datetimes` with the (adjusted) start and end of +#' the input vector. +#' @export +#' +#' @examples +#' dataset <- c("2023-08-15", "2023-08-20") +#' breaks <- Datetime_breaks(dataset) +#' Datetime_limits(breaks) +#' Datetime_limits(breaks, start = lubridate::ddays(1)) +#' Datetime_limits(breaks, length = lubridate::ddays(2)) +Datetime_limits <- function(x, + start = NULL, + length = NULL, + unit = "1 day", + ...) { + + min_date <- x %>% lubridate::as_datetime() %>% min() + if(!is.null(start)) { + min_date <- (min_date + start) + min_date %>% lubridate::as_datetime() + } + max_date <- + if(is.null(length)) { + x %>% lubridate::as_datetime() %>% max() + } else { + y <- (min_date + length) + y %>% lubridate::as_datetime() + } + + c(lubridate::floor_date(min_date, unit = unit, ...), + lubridate::ceiling_date(max_date, unit = unit, ...)) +} \ No newline at end of file diff --git a/README.Rmd b/README.Rmd index 9d14770..0d9cee5 100644 --- a/README.Rmd +++ b/README.Rmd @@ -90,7 +90,7 @@ There is a wide range of options to the `gg_day()` function to customize the out ```{r, fig.retina=2} dataset %>% gg_day( - col = MEDI >= 250, scales = "fixed", size = 0.5) + + aes_col = MEDI >= 250, scales = "fixed", size = 0.5) + scale_color_discrete(type = c("orange", "skyblue")) ``` @@ -103,7 +103,7 @@ sample.data.environment %>% gg_day( start.date = "2023-08-18", y.axis = `MELANOPIC EDI`, - col = Source, + aes_col = Source, scales = "fixed", geom = "line") ``` @@ -114,7 +114,7 @@ sample.data.environment %>% gg_day( end.date = "2023-08-15", y.axis = `MELANOPIC EDI`, - col = Source, + aes_col = Source, scales = "fixed", geom = "boxplot", group = interaction(Source, Datetime.rounded)) + diff --git a/README.md b/README.md index 7815636..1fa6e58 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ options. You can also override most of the defaults, e.g., for different ``` r dataset %>% gg_day( - col = MEDI >= 250, scales = "fixed", size = 0.5) + + aes_col = MEDI >= 250, scales = "fixed", size = 0.5) + scale_color_discrete(type = c("orange", "skyblue")) #> Scale for colour is already present. #> Adding another scale for colour, which will replace the existing scale. @@ -147,7 +147,7 @@ sample.data.environment %>% gg_day( start.date = "2023-08-18", y.axis = `MELANOPIC EDI`, - col = Source, + aes_col = Source, scales = "fixed", geom = "line") #> Only Dates will be used from start.date and end.date input. If you also want to set Datetimes or Times, consider using the `filter_Datetime()` function instead. @@ -170,7 +170,7 @@ sample.data.environment %>% gg_day( end.date = "2023-08-15", y.axis = `MELANOPIC EDI`, - col = Source, + aes_col = Source, scales = "fixed", geom = "boxplot", group = interaction(Source, Datetime.rounded)) + diff --git a/_pkgdown.yml b/_pkgdown.yml index 4cac854..2c4ab87 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -15,20 +15,29 @@ reference: - import - import.Statechanges - - title: Process + - title: Insight desc: > - This section includes functions to process light logger data, e.g., to - validate and clean data, to filter, cut or aggreagate data, or to join - datasets. + This section includes functions to gain more insight into light logger. + Functions in this section will not return a version of the input dataset, + but rather information based on it. contents: + - count.difftime - dominant_epoch - gapless_Datetimes - - gap_handler - gap_finder + + - title: Validate & Process + desc: > + This section includes functions to process light logger data, e.g., to + validate and clean data, to filter, cut or aggreagate data, or to join + datasets. All of these functions will return a version of the input dataset. + contents: + - gap_handler - cut_Datetime - aggregate_Datetime - create_Time.data - filter_Datetime + - filter_Datetime_multiple - filter_Date - filter_Time - join.datasets @@ -53,7 +62,15 @@ reference: contents: - gg_overview - gg_day + - gg_days + + - title: Helpers + desc: > + This section includes helper functions that are used in the other sections. + contents: - symlog_trans + - Datetime_breaks + - Datetime_limits - title: Datasets desc: > diff --git a/man/Datetime_breaks.Rd b/man/Datetime_breaks.Rd new file mode 100644 index 0000000..62c1ccb --- /dev/null +++ b/man/Datetime_breaks.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/visualize_helper.R +\name{Datetime_breaks} +\alias{Datetime_breaks} +\title{Create a (shifted) sequence of Datetimes for axis breaks} +\usage{ +Datetime_breaks(x, shift = lubridate::duration(12, "hours"), by = "1 day") +} +\arguments{ +\item{x}{a vector of \code{Datetimes}} + +\item{shift}{a \code{numeric} giving the number of \code{duration} object, e.g. +\code{lubridate::duration(12, "hours")}} + +\item{by}{a \code{character} scalar giving the unit of the interval in +\code{\link[base:seq]{base::seq()}}} +} +\value{ +a \code{vector} of \code{Datetimes} +} +\description{ +Take a vector of Datetimes and create a sequence of Datetimes with a given +shift and interval. This is a helper function to create breaks for plotting, +e.g. in \code{\link[=gg_days]{gg_days()}}, and is best used in conjunction with +\code{\link[=Datetime_limits]{Datetime_limits()}}. The function is a thin wrapper around \code{\link[=seq]{seq()}}. +} +\examples{ +dataset <- c("2023-08-15", "2023-08-20") +Datetime_breaks(dataset) +Datetime_breaks(dataset, shift = 0) +Datetime_breaks(dataset, by = "12 hours") +} diff --git a/man/Datetime_limits.Rd b/man/Datetime_limits.Rd new file mode 100644 index 0000000..d89d8fb --- /dev/null +++ b/man/Datetime_limits.Rd @@ -0,0 +1,42 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/visualize_helper.R +\name{Datetime_limits} +\alias{Datetime_limits} +\title{Find or set sensible limits for Datetime axis} +\usage{ +Datetime_limits(x, start = NULL, length = NULL, unit = "1 day", ...) +} +\arguments{ +\item{x}{a vector of \code{Datetimes}} + +\item{start}{optional \code{duration} object, e.g. \code{lubridate::ddays(1)} that +shifts the start of the \code{Datetime} vector by this amount.} + +\item{length}{optional \code{duration} object, e.g. \code{lubridate::ddays(7)} that +shifts the end of the \code{Datetime} vector by this amount from the (adjusted) +start.} + +\item{unit}{a \code{character} scalar giving the unit of rounding in +\code{\link[lubridate:round_date]{lubridate::floor_date()}} and \code{\link[lubridate:round_date]{lubridate::ceiling_date()}}} + +\item{...}{other arguments passed to \code{\link[lubridate:round_date]{lubridate::floor_date()}} and +\code{\link[lubridate:round_date]{lubridate::ceiling_date()}}} +} +\value{ +a 2 item \code{vector} of \code{Datetimes} with the (adjusted) start and end of +the input vector. +} +\description{ +Take a vector of \code{Datetimes} and return the start of the first and end of the +last day of data. The \code{start} and the \code{length} can be adjusted by +\code{durations}, like \code{\link[lubridate:duration]{lubridate::ddays()}}. It is used in the \code{\link[=gg_days]{gg_days()}} +function to return a sensible axis. This function is a thin wrapper around +\code{\link[lubridate:round_date]{lubridate::floor_date()}} and \code{\link[lubridate:round_date]{lubridate::ceiling_date()}}. +} +\examples{ +dataset <- c("2023-08-15", "2023-08-20") +breaks <- Datetime_breaks(dataset) +Datetime_limits(breaks) +Datetime_limits(breaks, start = lubridate::ddays(1)) +Datetime_limits(breaks, length = lubridate::ddays(2)) +} diff --git a/man/count.difftime.Rd b/man/count.difftime.Rd new file mode 100644 index 0000000..a936fd5 --- /dev/null +++ b/man/count.difftime.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helper.R +\name{count.difftime} +\alias{count.difftime} +\title{Counts the Time differences (epochs) per group (in a grouped dataset)} +\usage{ +count.difftime(dataset, Datetime.colname = Datetime) +} +\arguments{ +\item{dataset}{A light logger dataset. Expects a \code{dataframe}. If not imported +by \link{LightLogR}, take care to choose a sensible variable for the +\code{Datetime.colname}.} + +\item{Datetime.colname}{column name that contains the datetime. Defaults to +\code{"Datetime"} which is automatically correct for data imported with +\link{LightLogR}. Expects a \code{symbol}. Needs to be part of the \code{dataset}.} +} +\value{ +a \code{tibble} with the number of occurences of each time difference per +group +} +\description{ +Counts the Time differences (epochs) per group (in a grouped dataset) +} +\examples{ +#get a dataset with irregular intervals +filepath <- system.file("extdata/sample_data_LYS.csv", package = "LightLogR") +dataset <- import$LYS(filepath) + +#count.difftime returns the number of occurences of each time difference +#and is more comprehensive in terms of a summary than `gap_finder` or +#`dominant_epoch` +count.difftime(dataset) +dominant_epoch(dataset) +gap_finder(dataset) + +#irregular data can be regularized with `aggregate_Datetime` +dataset \%>\% aggregate_Datetime(unit = "15 secs") \%>\% count.difftime() +} diff --git a/man/filter_Datetime.Rd b/man/filter_Datetime.Rd index c1c97e3..edb1e2a 100644 --- a/man/filter_Datetime.Rd +++ b/man/filter_Datetime.Rd @@ -13,6 +13,7 @@ filter_Datetime( length = NULL, full.day = FALSE, tz = NULL, + only_Id = NULL, filter.expr = NULL ) @@ -54,6 +55,8 @@ on to avoid empty days in plotting with \code{\link[=gg_day]{gg_day()}}.} \item{tz}{Timezone of the start/end times. If \code{NULL} (the default), it will take the timezone from the \code{Datetime.colname} column.} +\item{only_Id}{An expression of \code{ids} where the filtering should be applied to. If \code{NULL} (the default), the filtering will be applied to all \code{ids}. Based on the this expression, the dataset will be split in two and only where the given expression evaluates to \code{TRUE}, will the filtering take place. Afterwards both sets are recombined and sorted by \code{Datetime}.} + \item{filter.expr}{Advanced filtering conditions. If not \code{NULL} (default) and given an \code{expression}, this is used to \code{\link[dplyr:filter]{dplyr::filter()}} the results. This can be useful to filter, e.g. for group-specific conditions, like starting after the first two days of measurement (see examples).} \item{...}{Parameter handed over to \code{\link[lubridate:round_date]{lubridate::round_date()}} and siblings} diff --git a/man/filter_Datetime_multiple.Rd b/man/filter_Datetime_multiple.Rd new file mode 100644 index 0000000..6fc66a1 --- /dev/null +++ b/man/filter_Datetime_multiple.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/filter_Datetime.R +\name{filter_Datetime_multiple} +\alias{filter_Datetime_multiple} +\title{Filter multiple times based on a list of arguments.} +\usage{ +filter_Datetime_multiple(dataset, arguments, filter_function = filter_Datetime) +} +\arguments{ +\item{dataset}{A light logger dataset} + +\item{arguments}{A list of arguments to be passed to \code{\link[=filter_Datetime]{filter_Datetime()}} or +\code{\link[=filter_Date]{filter_Date()}}. each list entry must itself be a list of arguments, e.g, +\code{list(start = "2021-01-01", only_Id = quote(Id == 216))}. Expressions have +to be quoted with \code{\link[=quote]{quote()}} or \code{\link[rlang:expr]{rlang::expr()}}.} + +\item{filter_function}{The function to be used for filtering, either +\code{filter_Datetime} (the default) or \code{filter_Date}} +} +\value{ +A dataframe with the filtered data +} +\description{ +\code{\link[=filter_Datetime_multiple]{filter_Datetime_multiple()}} is a wrapper around \code{\link[=filter_Datetime]{filter_Datetime()}} or +\code{\link[=filter_Date]{filter_Date()}} that allows the cumulative filtering of \code{Datetimes} based on +varying filter conditions. It is most useful in conjunction with the +\code{only_Id} argument, e.g., to selectively cut off dates depending on +participants (see examples) +} +\examples{ +arguments <- list( + list(start = "2023-08-17", only_Id = quote(Source == "Participant")), + list(end = "2023-08-17", only_Id = quote(Source == "Environment"))) + #compare the unfiltered dataset + sample.data.environment \%>\% gg_overview(Id.colname = Source) + #compare the unfiltered dataset + sample.data.environment \%>\% + filter_Datetime_multiple(arguments = arguments, filter_Date) \%>\% + gg_overview(Id.colname = Source) +} diff --git a/man/gg_day.Rd b/man/gg_day.Rd index 3d73c88..e3dbc50 100644 --- a/man/gg_day.Rd +++ b/man/gg_day.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/gg_day.r \name{gg_day} \alias{gg_day} -\title{Create a simple plot of light logger data, facetted by Day} +\title{Create a simple Time-of-Day plot of light logger data, faceted by Date} \usage{ gg_day( dataset, @@ -10,7 +10,8 @@ gg_day( end.date = NULL, x.axis = Datetime, y.axis = MEDI, - col = NULL, + aes_col = NULL, + aes_fill = NULL, group = NULL, geom = "point", scales = "fixed", @@ -25,6 +26,7 @@ gg_day( subtitle = NULL, interactive = FALSE, facetting = TRUE, + jco_color = TRUE, ... ) } @@ -35,9 +37,9 @@ by \link{LightLogR}, take care to choose a sensible variable for the \code{x.axi \item{start.date, end.date}{Choose an optional start or end date within your \code{dataset}. Expects a \code{date}, which can also be a \code{character} that is interpretable as a date, e.g., \code{"2023-06-03"}. If you need a Datetime or -want to cut specific times of each day, use the \link{filter_Datetime} function. -Defaults to \code{NULL}, which means that the plot starts/ends with the -earliest/latest date within the \code{dataset}.} +want to cut specific times of each day, use the \code{\link[=filter_Datetime]{filter_Datetime()}} +function. Defaults to \code{NULL}, which means that the plot starts/ends with +the earliest/latest date within the \code{dataset}.} \item{x.axis, y.axis}{column name that contains the datetime (x, defaults to \code{"Datetime"} which is automatically correct for data imported with @@ -46,10 +48,10 @@ melanopic EDI, which is a standard measure of stimulus strength for the nonvisual effects of light). Expects a \code{symbol}. Needs to be part of the \code{dataset}.} -\item{col}{optional column name that defines separate sets and colors them. -Expects anything that works with the layer data \code{\link[ggplot2:aes]{ggplot2::aes()}}. The -default color palette can be overwritten outside the function (see -examples).} +\item{aes_col, aes_fill}{optional arguments that define separate sets and +colors or fills them. Expects anything that works with the layer data +\code{\link[ggplot2:aes]{ggplot2::aes()}}. The default color palette can be overwritten outside the +function (see examples).} \item{group}{Optional column name that defines separate sets. Useful for certain geoms like \code{boxplot}.Expects anything that works with the layer @@ -57,9 +59,10 @@ data \code{\link[ggplot2:aes]{ggplot2::aes()}}} \item{geom}{What geom should be used for visualization? Expects a \code{character} \itemize{ -\item \code{"point"} for \code{\link[ggplot2:geom_point]{ggplot2::geom_point()}} (the default) +\item \code{"point"} for \code{\link[ggplot2:geom_point]{ggplot2::geom_point()}} \item \code{"line"} for \code{\link[ggplot2:geom_path]{ggplot2::geom_line()}} -\item as the value is just input into the \code{geom_} function from \link{ggplot2}, other variants might work as well, but are not tested. +\item \code{"ribbon"} for \code{\link[ggplot2:geom_ribbon]{ggplot2::geom_ribbon()}} +\item as the value is just input into the \code{geom_} function from \link{ggplot2}, other variants work as well, but are not extensively tested. }} \item{scales}{For \code{\link[ggplot2:facet_wrap]{ggplot2::facet_wrap()}}, should scales be "fixed", "free" @@ -95,18 +98,23 @@ at \code{\link[base:strptime]{base::strptime()}}} \item{interactive}{Should the plot be interactive? Expects a \code{logical}. Defaults to \code{FALSE}.} -\item{facetting}{Should an automated facet by day be applie? Default is \code{TRUE} and uses the \code{Day.data} variable that the function also creates if not present.} +\item{facetting}{Should an automated facet by day be applied? Default is +\code{TRUE} and uses the \code{Day.data} variable that the function also creates if +not present.} + +\item{jco_color}{Should the \code{\link[ggsci:scale_jco]{ggsci::scale_color_jco()}} color palette be used? +Defaults to \code{TRUE}.} \item{...}{Other options that get passed to the main geom function. Can be -used to adjust to adjust size or linetype.} +used to adjust to adjust size, linewidth, or linetype.} } \value{ A ggplot object } \description{ -\code{gg_day} will create a simple ggplot for every data in a dataset. The result -can further be manipulated like any ggplot. This will be sensible to refine -styling or guides. +\code{\link[=gg_day]{gg_day()}} will create a simple ggplot for every data in a dataset. The +result can further be manipulated like any ggplot. This will be sensible to +refine styling or guides. } \details{ Besides plotting, the function creates two new variables from the given @@ -117,7 +125,11 @@ Besides plotting, the function creates two new variables from the given } The default scaling of the y-axis is a \code{symlog} scale, which is a logarithmic -scale that only starts scaling after a given threshold (default = 0). This enables values of 0 in the plot, which are common in light logger data, and even enables negative values, which might be sensible for non-light data. See \code{\link[=symlog_trans]{symlog_trans()}} for details on tweaking this scale. The scale can also be changed to a normal or logarithmic scale - see the y.scale argument for more. +scale that only starts scaling after a given threshold (default = 0). This +enables values of 0 in the plot, which are common in light logger data, and +even enables negative values, which might be sensible for non-light data. See +\code{\link[=symlog_trans]{symlog_trans()}} for details on tweaking this scale. The scale can also be +changed to a normal or logarithmic scale - see the y.scale argument for more. } \examples{ #use `col`for separation of different sets @@ -128,7 +140,7 @@ end.date = "2023-08-16", x.axis = Datetime, y.axis = `MELANOPIC EDI`, y.axis.label = "mEDI (lx)", -col = Source) +aes_col = Source) plot #you can easily overwrite the color scale afterwards diff --git a/man/gg_days.Rd b/man/gg_days.Rd new file mode 100644 index 0000000..9c5fa10 --- /dev/null +++ b/man/gg_days.Rd @@ -0,0 +1,138 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/gg_days.R +\name{gg_days} +\alias{gg_days} +\title{Create a simple datetime plot of light logger data, faceted by group} +\usage{ +gg_days( + dataset, + x.axis = Datetime, + y.axis = MEDI, + aes_col = NULL, + aes_fill = NULL, + group = NULL, + geom = "line", + scales = "free_x", + x.axis.breaks = Datetime_breaks, + y.axis.breaks = c(-10^(5:0), 0, 10^(0:5)), + y.scale = "symlog", + y.scale.sc = FALSE, + x.axis.label = "Datetime", + y.axis.label = "Illuminance (lx, MEDI)", + x.axis.limits = Datetime_limits, + x.axis.format = "\%a \%D", + title = NULL, + subtitle = NULL, + interactive = FALSE, + facetting = TRUE, + ... +) +} +\arguments{ +\item{dataset}{A light logger dataset. Expects a \code{dataframe}. If not imported +by \link{LightLogR}, take care to choose a sensible variable for the \code{x.axis.}.} + +\item{x.axis, y.axis}{column name that contains the datetime (x, defaults to +\code{"Datetime"} which is automatically correct for data imported with +\link{LightLogR}) and the dependent variable (y, defaults to \code{"MEDI"}, or +melanopic EDI, which is a standard measure of stimulus strength for the +nonvisual effects of light). Expects a \code{symbol}. Needs to be part of the +\code{dataset}.} + +\item{aes_col, aes_fill}{optional input that defines separate sets and colors +or fills them. Expects anything that works with the layer data +\code{\link[ggplot2:aes]{ggplot2::aes()}}.} + +\item{group}{Optional column name that defines separate sets. Useful for +certain geoms like \code{boxplot}.Expects anything that works with the layer +data \code{\link[ggplot2:aes]{ggplot2::aes()}}} + +\item{geom}{What geom should be used for visualization? Expects a \code{character} +\itemize{ +\item \code{"point"} for \code{\link[ggplot2:geom_point]{ggplot2::geom_point()}} +\item \code{"line"} for \code{\link[ggplot2:geom_path]{ggplot2::geom_line()}} +\item \code{"ribbon"} for \code{\link[ggplot2:geom_ribbon]{ggplot2::geom_ribbon()}} +\item as the value is just input into the \code{geom_} function from \link{ggplot2}, other variants work as well, but are not extensively tested. +}} + +\item{scales}{For \code{\link[ggplot2:facet_wrap]{ggplot2::facet_wrap()}}, should scales be "fixed", "free" +or free in one dimension ("free_y" is the default). Expects a \code{character}.} + +\item{x.axis.breaks}{The (major) breaks of the x-axis. Defaults to +\code{\link[=Datetime_breaks]{Datetime_breaks()}}. The function has several options for adjustment. The +default setting place a major break every 12 hours, starting at 12:00 of +the first day.} + +\item{y.axis.breaks}{Where should breaks occur on the y.axis? Expects a +\verb{numeric vector} with all the breaks or a function that calculates them +based on the limits. If you want to activate the default behaviour of +\link{ggplot2}, you need to put in \code{\link[ggplot2:waiver]{ggplot2::waiver()}}.} + +\item{y.scale}{How should the y-axis be scaled? +\itemize{ +\item Defaults to \code{"symlog"}, which is a logarithmic scale that can also handle negative values. +\item \code{"log10"} would be a straight logarithmic scale, but cannot handle negative values. +\item \code{"identity"} does nothing (continuous scaling). +\item a transforming function, such as \code{\link[=symlog_trans]{symlog_trans()}} or \code{\link[scales:identity_trans]{scales::identity_trans()}}, which allow for more control. +}} + +\item{y.scale.sc}{\code{logical} for whether scientific notation shall be used. +Defaults to \code{FALSE}.} + +\item{x.axis.label, y.axis.label}{labels for the x- and y-axis. Expects a +\code{character}.} + +\item{x.axis.limits}{The limits of the x-axis. Defaults to +\code{\link[=Datetime_limits]{Datetime_limits()}}. Can and should be adjusted to shift the x-axis to +align different groups of data.} + +\item{x.axis.format}{The format of the x-axis labels. Defaults to \code{"\%a \%D"}, +which is the weekday and date. See \code{\link[base:strptime]{base::strptime()}} for more options.} + +\item{title}{Plot title. Expects a \code{character}.} + +\item{subtitle}{Plot subtitle. Expects a \code{character}.} + +\item{interactive}{Should the plot be interactive? Expects a \code{logical}. +Defaults to \code{FALSE}.} + +\item{facetting}{Should an automated facet by grouping be applied? Default is +\code{TRUE}.} + +\item{...}{Other options that get passed to the main geom function. Can be +used to adjust to adjust size, linewidth, or linetype.} +} +\value{ +A ggplot object +} +\description{ +\code{\link[=gg_days]{gg_days()}} will create a simple ggplot along the timeline. The result can +further be manipulated like any ggplot. This will be sensible to refine +styling or guides. Through the \code{x.axis.limits} arguments, the plot can be +much refined to align several groups of differing datetime ranges. It uses +the \code{\link[=Datetime_limits]{Datetime_limits()}} function to calculate the limits of the x-axis. +Another notable functions that are used are \code{\link[=Datetime_breaks]{Datetime_breaks()}} to calculate +the breaks of the x-axis. +} +\details{ +The default scaling of the y-axis is a \code{symlog} scale, which is a logarithmic +scale that only starts scaling after a given threshold (default = 0). This +enables values of 0 in the plot, which are common in light logger data, and +even enables negative values, which might be sensible for non-light data. See +\code{\link[=symlog_trans]{symlog_trans()}} for details on tweaking this scale. The scale can also be +changed to a normal or logarithmic scale - see the y.scale argument for more. +} +\examples{ +dataset <- +sample.data.environment \%>\% +dplyr::group_by(Source) \%>\% +aggregate_Datetime(unit = "5 mins") + +dataset \%>\% gg_days(y.axis = `MELANOPIC EDI`) +#restrict the x-axis to 3 days +dataset \%>\% +gg_days( +y.axis = `MELANOPIC EDI`, +x.axis.limits = \(x) Datetime_limits(x, length = lubridate::ddays(3)) +) +} diff --git a/man/import.Dataset.Rd b/man/import.Dataset.Rd index d9c6c3b..e1fd94b 100644 --- a/man/import.Dataset.Rd +++ b/man/import.Dataset.Rd @@ -21,7 +21,7 @@ by the \code{device.ext} spec to access the sample file): \itemize{ \item \code{"ActLumus"} (ActLumus.txt) \item \code{"LYS"} (LYS.csv) -\item \code{"Actiwatch_Spectrum"} (Actiwatch.csv) \emph{Note: as the \code{locale} argument use \code{readr::locale(encoding="latin1")} . This is due to the fact that the German Actiwatch software from which this sample file was taken, uses a different encoding than UTF-8.} +\item \code{"Actiwatch_Spectrum"} (Actiwatch.csv) \strong{Special Argument: \code{column_names}} A character vector containing column names in the order in which they appear in the file. This is necessary to find the starting point of actual data.\emph{Note: as the \code{locale} argument use \code{readr::locale(encoding="latin1")} . This is due to the fact that the German Actiwatch software from which this sample file was taken, uses a different encoding than UTF-8.} }} \item{...}{Parameters that get handed down to the specific import functions} @@ -80,7 +80,7 @@ just work out of the box. To get an overview, you can simply call the is maintained. \if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}Datetime\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}TEMPERATURE\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}LIGHT\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}MEDI\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}Id\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
---|---|---|---|---|
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:04:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.88\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}21,847.64\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,660.74\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:05:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.88\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}22,033.77\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,834.91\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:06:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.81\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}21,769.50\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,600.82\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:07:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.69\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}21,177.20\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,061.68\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:08:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.44\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,738.98\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}19,662.14\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:09:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.31\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,255.17\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}19,203.94\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}Datetime\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}TEMPERATURE\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}LIGHT\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}MEDI\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}Id\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
---|---|---|---|---|
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:04:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.88\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}21,847.64\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,660.74\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:05:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.88\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}22,033.77\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,834.91\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:06:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.81\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}21,769.50\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,600.82\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:07:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.69\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}21,177.20\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,061.68\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:08:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.44\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,738.98\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}19,662.14\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{
}}\if{html}{\out{ }}\if{html}{\out{}}2023-07-14 13:09:18\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}29.31\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}20,255.17\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}19,203.94\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{}}sample_data_ActLumus\if{html}{\out{}}\if{html}{\out{ }}\if{html}{\out{ | }}\if{html}{\out{