R/utils.R

Defines functions shush require_pkg str_extract_ double_quote_ single_quote_ get_names get_class count_na class_collapse swap extract_seconds interval_mean midday_change flat_posixt

# Sort by type or alphabetical order.

flat_posixt <- function(posixt, base = as.Date("1970-01-01"),
                        force_tz = TRUE, tz = "UTC") {
    assert_posixt(posixt, null.ok = FALSE)
    checkmate::assert_date(base, len = 1, all.missing = FALSE)
    checkmate::assert_flag(force_tz)
    checkmate::assert_choice(tz, OlsonNames())

    lubridate::date(posixt) <- base

    if (isTRUE(force_tz)) {
        lubridate::force_tz(posixt, tz)
    } else {
        posixt
    }
}

midday_change <- function(time) {
    checkmate::assert_multi_class(time, c("hms", "POSIXct", "POSIXlt"))

    if (hms::is_hms(time)) time <- as.POSIXct(time)
    time <- flat_posixt(time)

    dplyr::case_when(
        lubridate::hour(time) < 12 ~ lubridate::`day<-`(time, 2),
        TRUE ~ time
    )
}

interval_mean <- function(start, end, ambiguity = 24) {
    classes <- c("Duration", "difftime", "hms", "POSIXct", "POSIXlt")

    checkmate::assert_multi_class(start, classes)
    checkmate::assert_multi_class(end, classes)
    checkmate::assert_choice(ambiguity, c(0, 24 , NA))

    start <- cycle_time(hms::hms(extract_seconds(start)),
                        cycle = lubridate::ddays())
    end <- cycle_time(hms::hms(extract_seconds(end)),
                      cycle = lubridate::ddays())
    interval <- shush(assign_date(start, end, ambiguity = ambiguity))
    mean <- as.numeric(start) + (as.numeric(interval) / 2)

    hms::hms(mean)
}

extract_seconds <- function(x) {
    classes <- c("Duration", "difftime", "hms", "POSIXct", "POSIXlt",
                 "Interval")

    checkmate::assert_multi_class(x, classes)

    if (lubridate::is.POSIXt(x) || lubridate::is.difftime(x)) {
        as.numeric(hms::as_hms(x))
    } else {
        as.numeric(x)
    }
}

swap <- function(x, y, condition = TRUE) {
    assert_identical(x, y, type = "class")
    assert_identical(x, y, condition, type = "length")
    checkmate::assert_logical(condition)

    first_arg <- x
    second_arg <- y

    x <- dplyr::if_else(condition, second_arg, first_arg)
    y <- dplyr::if_else(condition, first_arg, second_arg)

    list(x = x, y = y)
}

class_collapse <- function(x) single_quote_(paste0(class(x), collapse = "/"))

count_na <- function(x) {
    checkmate::assert_atomic(x)

    length(which(is.na(x)))
}

get_class <- function(x) {
    if (is.list(x)) {
        vapply(x, function(x) class(x)[1], character(1))
    } else {
        class(x)[1]
    }
}

get_names <- function(...) {
    out <- lapply(substitute(list(...))[-1], deparse) %>%
        vapply(unlist, character(1)) %>%
        noquote()

    gsub("\\\"","", out)
}

single_quote_ <- function(x) paste0("'", x, "'")
double_quote_ <- function(x) paste0("\"", x, "\"")

str_extract_ <- function(string, pattern, ignore_case = FALSE, perl = TRUE,
                         fixed = FALSE, use_bytes = FALSE, invert = FALSE) {
    checkmate::assert_string(pattern)
    checkmate::assert_flag(ignore_case)
    checkmate::assert_flag(perl)
    checkmate::assert_flag(fixed)
    checkmate::assert_flag(use_bytes)
    checkmate::assert_flag(invert)

    match <- regexpr(pattern, string, ignore.case = ignore_case, perl = perl,
                     fixed = fixed, useBytes = use_bytes)
    out <- rep(NA, length(string))
    out[match != -1 & !is.na(match)] <- regmatches(string, match,
                                                   invert = invert)
    out
}

require_pkg <- function(...) {
    out <- list(...)

    lapply(out, checkmate::assert_string,
           pattern = "^[A-Za-z][A-Za-z0-9.]+[A-Za-z0-9]$")

    if (!identical(unique(unlist(out)), unlist(out))) {
        cli::cli_abort("'...' cannot have duplicated values.")
    }

    pkg <- unlist(out)
    namespace <- vapply(pkg, require_namespace, logical(1),
                        quietly = TRUE, USE.NAMES = FALSE)
    pkg <- pkg[!namespace]

    if (length(pkg) == 0) {
        invisible(NULL)
    } else {
        cli::cli_abort(paste0(
            "This function requires the {single_quote_(pkg)} package{?s} ",
             "to run. You can install {?it/them} by running:", "\n\n",
             "install.packages(",
             "{paste(double_quote_(pkg), collapse = ', ')})"
            ))
    }
}

shush <- function(x, quiet = TRUE) {
    if (isTRUE(quiet)) {
        suppressMessages(suppressWarnings(x))
    } else {
        x
    }
}

Try the mctq package in your browser

Any scripts or data that you put into this service are public.

mctq documentation built on March 7, 2023, 8:22 p.m.