Package 'bkbase'

Title: Package Utility Functions
Description: A collection of package utility functions written in 'base' R.
Authors: Brett Klamer [aut, cre]
Maintainer: Brett Klamer <[email protected]>
License: MIT + file LICENSE
Version: 0.0.1
Built: 2026-06-10 07:18:18 UTC
Source: https://bitbucket.org/bklamer/bkbase

Help Index


Equality operator that is NA-aware

Description

Infix equality operator that resolves missing values instead of propagating them.

Usage

x %==% y

Arguments

x

(atomic vector)
The left-hand side values to compare.

y

(atomic vector)
The right-hand side values to compare.

Details

⁠base::==⁠ returns NA whenever either operand is NA. ⁠%==%⁠ resolves those positions and never returns NA.

For each pair of compared elements the result is

  • TRUE when both x and y are NA.

  • FALSE when exactly one of x and y is NA.

  • The value of x == y when neither is NA.

NaN is treated the same as NA, because is.na(NaN) is TRUE. NaN %==% NaN is TRUE and NaN %==% NA is TRUE.

x and y are recycled to a common length following standard R rules.

Value

A logical vector of length max(length(x), length(y)). The result never contains NA.

See Also

base::Comparison, %in2%

Examples

#----------------------------------------------------------------------------
# %==% examples
#----------------------------------------------------------------------------
library(bkbase)

# both NA gives TRUE, exactly one NA gives FALSE
1:3 %==% c(1:2, NA)   # TRUE TRUE FALSE
NA %==% NA            # TRUE

# NaN is treated the same as NA
1:3 %==% c(1:2, NaN)  # TRUE TRUE FALSE
NaN %==% NaN          # TRUE
NaN %==% NA           # TRUE

# base `==` propagates NA instead
1:3 == c(1:2, NA)     # TRUE TRUE NA
1:3 == c(1:2, NaN)    # TRUE TRUE NA

Value matching that propagates NA

Description

Infix operator for matching that forces NA in x to propagate in results.

Usage

x %in2% table

Arguments

x

(atomic vector)
Values to match in table.

table

(atomic vector)
The reference set against which membership is evaluated.

Details

⁠base::%in%⁠ treats NA in x as an ordinary value. NA %in% c(1, 2, 3) is FALSE and NA %in% c(NA) is TRUE. You may not want this behavior because membership of a missing value is itself unknown.

⁠%in2%⁠ instead returns NA for every position where x is NA, regardless of whether table contains NA. For all non-missing elements of x, the result equals ⁠base::%in%⁠.

NaN is treated the same as NA and also propagates to NA.

Value

A logical vector with length length(x).

See Also

base::%in%, base::match(), %==%

Examples

#----------------------------------------------------------------------------
# %in2% examples
#----------------------------------------------------------------------------
library(bkbase)

# base::`%in%` behavior
NA %in% c(1, 2, 3)            # FALSE
NA %in% c(NA)                 # TRUE

# bkbase::`%in2%` (always propagate NA from x)
NA %in2% c(1, 2, 3)           # NA
NA %in2% c(NA)                # NA

# Mixed vectors
c(NA, 1) %in%  c(1, 2, 3)     # FALSE TRUE
c(NA, 1) %in2% c(1, 2, 3)     # NA    TRUE

c(NA, 1) %in%  c(NA, 2, 3)    # TRUE  FALSE
c(NA, 1) %in2% c(NA, 2, 3)    # NA    FALSE

Are all values TRUE

Description

Returns TRUE if all values in a logical vector are TRUE. A stricter, surprise-free version of base::all().

Usage

all2(x, na.rm = FALSE)

Arguments

x

(logical)
The logical vector to be checked if all elements are TRUE. Any non-logical input returns FALSE.

na.rm

(Scalar logical: c(FALSE, TRUE))
Whether or not to remove NAs from x before evaluating.

Details

Suppose you have a numeric vector y and want to validate all values are greater than zero using base::all(y > 0). If y contains NAs and all nonmissing elements are greater than 0, the result will be NA. You then might use base::all(y > 0, na.rm = TRUE), however, this assumes NAs are ok to exclude. In this scenario, all2(y > 0) would return FALSE instead of NA.

all(NULL) and all(logical(0)) both return TRUE. all2() returns FALSE for both cases.

all(NA, na.rm = TRUE) returns TRUE. all2(NA, na.rm = TRUE) returns FALSE.

Value

Scalar logical

See Also

base::all(), any2()

Examples

#----------------------------------------------------------------------------
# all2() examples
#----------------------------------------------------------------------------
library(bkbase)

x <- c(1, 2, 3, NA)

all2(x > 0)
all(x > 0)

all2(x > 0, na.rm = TRUE)
all(x > 0, na.rm = TRUE)

all2(NULL)
all(NULL)

all2(logical(0))
all(logical(0))

all2(numeric(0))
all(numeric(0))

all2(NA, na.rm = TRUE)
all(NA, na.rm = TRUE)

all2(NA, na.rm = FALSE)
all(NA, na.rm = FALSE)

Logical AND with NA tolerance

Description

Compute a position-wise logical AND across multiple logical inputs, allowing up to a specified fraction of missing values before returning NA.

Usage

and(..., .na_allowed = 0.2)

Arguments

...

Logical vectors of equal length, or a single logical matrix/data.frame. Matrix/data.frame inputs must have at least one column. Inputs are coerced to logical via as.logical, preserving NA.

.na_allowed

(Scalar numeric: 0.2; ⁠[0, 1]⁠)
Maximum allowed fraction of NA per position before the result is set to NA when no input is FALSE.

Details

This is a tolerance-aware variant of logical conjunction over multiple inputs (e.g., x & y & z). Each output position corresponds to one vector index, or to one row when a matrix or data.frame is supplied. The result is FALSE when any input at that position is FALSE. Otherwise, the result is NA when the fraction of missing values exceeds .na_allowed. If the missing fraction is within tolerance, missing values are treated as TRUE and the result is TRUE.

For each position (row) ii across pp inputs, let mim_i be the number of NAs and fif_i be the number of FALSEs. Define the missing fraction ri=mi/pr_i = m_i / p. Then:

andi={NA,if ri>.na_allowed and fi=0,TRUE,if ri.na_allowed and fi=0,FALSE,if fi1.\text{and}_i = \begin{cases} \mathrm{NA}, & \text{if } r_i > \text{.na\_allowed} \text{ and } f_i = 0, \\ \text{TRUE}, & \text{if } r_i \le \text{.na\_allowed} \text{ and } f_i = 0, \\ \text{FALSE}, & \text{if } f_i \ge 1. \end{cases}

Notes:

  1. When .na_allowed = 0, behavior matches strict AND: NAs propagate only when no input is FALSE.

  2. When .na_allowed=1\text{.na\_allowed} = 1, missingness never forces NA. NAs are treated as TRUE, so the result is FALSE iff any FALSE is present, otherwise TRUE.

Value

A logical vector with values TRUE, FALSE, or NA per the rule in Details.

See Also

base::Logic

Examples

#----------------------------------------------------------------------------
# and() examples
#----------------------------------------------------------------------------
library(bkbase)

x <- c(TRUE, TRUE, TRUE, FALSE, TRUE)
y <- c(TRUE, TRUE, NA, TRUE, NA)
z <- c(TRUE, NA, TRUE, TRUE, NA)

# Base R strict AND
x & y & z

# NA tolerance at 20%
and(x, y, z, .na_allowed = 0.2)

# NA tolerance at 40%
and(x, y, z, .na_allowed = 0.4)

# Single data.frame input
df <- data.frame(x = x, y = y, z = z)
and(df, .na_allowed = 0.4)

# FALSE dominates even when NA is present
and(FALSE, NA, .na_allowed = 0)

Are any nonmissing values TRUE

Description

Returns TRUE if any nonmissing values in a logical vector are TRUE.

Usage

any2(x)

Arguments

x

(logical)
The logical vector to be checked if any element is TRUE.

Details

Missing values are excluded before evaluation. Compared with base::any(), any2() has stricter behavior:

  • any2() never returns NA.

  • any2() returns FALSE for non-logical input.

  • any2() returns FALSE for logical(0) and NULL.

Value

Scalar logical

See Also

base::any(), all2()

Examples

#----------------------------------------------------------------------------
# any2() examples
#----------------------------------------------------------------------------
library(bkbase)

x <- c(1, 2, 3, NA)
any2(x < 0)
any(x < 0, na.rm = TRUE)
any(x < 0, na.rm = FALSE)

any2(NA)
any(NA)

any2(1L)
any(1L)

any2(c(TRUE, NA))
any2(c(FALSE, NA))
any2(c(NA, NA))

any2(logical(0))
any(logical(0))

any2(NULL)
any(NULL)

Coerce to NA

Description

Coerce's input to missing values (NA) of the same type.

Usage

as_na(x)

Arguments

x

(object)
The object to coerce to NAs.

Value

Object of same class as x.

Examples

#----------------------------------------------------------------------------
# as_na() examples
#----------------------------------------------------------------------------
library(bkbase)

as_na(data.frame(a = 1:3))
as_na(matrix(1:3))
as_na(list(a = 1:3))
as_na(1:3)
as_na(letters[1:3])
as_na(factor(letters[1:3]))
as_na(as.Date("2020-01-01"))

Comma separated words

Description

Converts an atomic vector into a string of comma separated elements.

Usage

csw(
  x,
  n = Inf,
  quote = TRUE,
  ellipsis = TRUE,
  and = FALSE,
  or = FALSE,
  period = FALSE,
  width = 70L
)

Arguments

x

(atomic vector)
Will be coerced to character, then converted into a string of comma separated elements. NA elements are coerced to the string "NA" with no special treatment.

n

(scalar integer: Inf; [1, Inf])
The number of elements in x to include before truncating. Set as Inf to never truncate.

quote

(scalar logical: TRUE)
Whether or not to wrap elements in quotes. Elements containing ⁠'⁠ are wrapped in double quotes. Elements containing ⁠"⁠ are wrapped in single quotes. Elements containing both ⁠'⁠ and ⁠"⁠ are wrapped in double quotes.

ellipsis

(scalar logical: TRUE)
Whether or not to append "..." when x is truncated by n.

and

(scalar logical: FALSE)
Whether or not to insert ", and" before the last element. Has no effect when x has fewer than two elements or when x is truncated to n elements. Cannot be TRUE when or = TRUE.

or

(scalar logical: FALSE)
Whether or not to insert ", or" before the last element. Has no effect when x has fewer than two elements or when x is truncated to n elements. Cannot be TRUE when and = TRUE.

period

(scalar logical: FALSE)
Whether or not to end the string with a period. Has no effect when x is truncated to n elements.

width

(scalar integer: 70L; [1, Inf])
The column number at which a new line should be inserted. Set as Inf to never insert a new line.

Details

Elements are coerced to character with as.character(). Pre-format numeric values that require specific precision before passing to csw().

When and = TRUE or or = TRUE with three or more elements, a comma is included before the connector (Oxford-comma style), e.g. "a, b, and c". With exactly two elements, no comma is used, e.g. "a and b".

The period added by period = TRUE is appended after word wrapping, so the final line may exceed width by one character.

Value

A character vector of length 0 or 1.

Examples

#----------------------------------------------------------------------------
# csw() example
#----------------------------------------------------------------------------
library(bkbase)
set.seed(1)

csw(letters)

c(
  "Lorem","ipsum","dolor","sit","amet","consectetur","adipiscing","elit",
  "sed","do","eiusmod","tempor","incididunt","ut","labore","et","dolore",
  "magna","aliqua","Ut","enim","ad","minim","veniam","quis","nostrud"
) |>
  csw() |>
  message()

rnorm(30) |>
  round(digits = 1) |>
  csw(quote = FALSE, and = TRUE) |>
  message()

Capture unevaluated dots

Description

Capture the expressions supplied in ... without evaluating them. Use dots() when the expressions should remain as language objects. Use dots_char() when the expressions should be returned as text.

Usage

dots(..., .names = TRUE, .duplicate_names = "warn")

dots_char(..., .names = TRUE, .duplicate_names = "warn")

Arguments

...

Expressions to capture.

.names

(Scalar logical: TRUE)
Whether to fill missing names with deparsed expressions. Explicit names are always preserved.

.duplicate_names

(Scalar character: "warn"; c("ignore", "warn", "stop"))
Action to take when duplicate names are found. Values are matched exactly. Duplicate names are checked after missing names have been filled. Repeated expressions in ... are allowed. The duplicate-name policy is applied only if .names = TRUE.

Value

An object with one element for each expression in .... dots() returns a list of unevaluated expressions. dots_char() returns a character vector of deparsed expressions. If .names = TRUE, missing names are filled with the deparsed expression. If .names = FALSE, missing names are left missing. Empty ... returns list() from dots() and character(0) from dots_char().

Examples

#----------------------------------------------------------------------------
# dots() examples
#----------------------------------------------------------------------------
library(bkbase)

a <- 1:5

dots(a, 6:10, x = 3)
dots_char(a, 6:10, x = 3)
dots(a, 6:10, x = 3, .names = FALSE)

Fast deparse

Description

A convenience function between base::deparse() and base::deparse1().

Usage

fdeparse(expr, width.cutoff = 500L, ...)

Arguments

expr

(expression)
Any R expression.

width.cutoff

(integer: 500L)
The cutoff at which line-breaking occurs. See base::deparse1() if you need more.

...

Further arguments passed to base::deparse().

Value

character vector

Examples

#----------------------------------------------------------------------------
# fdeparse() example
#----------------------------------------------------------------------------
library(bkbase)

fdeparse(y ~ x)

Fast formula

Description

Create a formula object from known-good string input. A fast, unsafe alternative to stats::formula().

Usage

fformula(x, env = parent.frame())

Arguments

x

(string)
The string to be converted into a formula.

env

(environment: base::parent.frame())
An environment to associate with the result.

Value

A formula object whose environment is set to env.

See Also

stats::formula()

Examples

#----------------------------------------------------------------------------
# fformula() example
#----------------------------------------------------------------------------
library(bkbase)

fformula("y ~ x")

Fast mean

Description

Calculates the arithmetic mean after excluding missing values. A fast, unsafe alternative to base::mean(x, na.rm = TRUE) for numeric vectors.

Usage

fmean(x)

Arguments

x

(numeric)
The numeric vector used to calculate the mean.

Value

Scalar numeric

See Also

base::mean()

Examples

#----------------------------------------------------------------------------
# fmean() example
#----------------------------------------------------------------------------
library(bkbase)

fmean(1:3)
fmean(c(1:3, NA))
fmean(NA)
fmean(numeric(0))

Fast median

Description

Calculates the median after excluding missing values. A fast, unsafe alternative to stats::median(x, na.rm = TRUE).

Usage

fmedian(x, is_sorted = FALSE)

Arguments

x

(numeric)
The numeric vector used to calculate the median.

is_sorted

(Scalar logical: FALSE)
Whether or not x is already sorted in ascending order. Only set is_sorted = TRUE when x is guaranteed to already be sorted.

Value

Scalar numeric

See Also

stats::median()

Examples

#----------------------------------------------------------------------------
# fmedian() example
#----------------------------------------------------------------------------
library(bkbase)

fmedian(1:3)
fmedian(c(1:3, NA))
fmedian(NA)
fmedian(numeric(0))

Fast number of columns in a data frame

Description

Get the number of columns in a data frame. A fast, unsafe alternative to base::ncol().

Usage

fncol(x)

Arguments

x

(data.frame)
The data frame to get the number of columns.

Value

Scalar integer

See Also

base::ncol()

Examples

#----------------------------------------------------------------------------
# fncol() examples
#----------------------------------------------------------------------------
library(bkbase)

x <- data.frame(a = 1)
fncol(x)

Fast number of rows in a data frame

Description

Get the number of rows in a data frame. A fast, unsafe alternative to base::nrow().

Usage

fnrow(x)

Arguments

x

(data.frame)
The data frame to get the number of rows.

Value

Scalar integer

See Also

base::nrow()

Examples

#----------------------------------------------------------------------------
# fnrow() examples
#----------------------------------------------------------------------------
library(bkbase)

x <- data.frame(a = 1)
fnrow(x)

Fast outer

Description

A fast, unsafe alternative to base::outer().

Usage

fouter(x, y, fun)

Arguments

x

(atomic vector)
The first argument for function fun.

y

(atomic vector)
The second argument for function fun.

fun

(function)
The function to apply to x and y.

Value

A matrix with length(x) rows and length(y) columns. Values are returned by fun() after pairwise expansion of x and y.

See Also

base::outer()

Examples

#----------------------------------------------------------------------------
# fouter() example
#----------------------------------------------------------------------------
library(bkbase)

x <- c(1, 2)
y <- c(3, 4)

fouter(x, y, `+`)

Fast standard deviation

Description

Calculates the standard deviation after excluding missing values. A fast, unsafe alternative to stats::sd(x, na.rm = TRUE).

Usage

fsd(x)

Arguments

x

(numeric)
The numeric vector to calculate the standard deviation.

Value

Scalar numeric

See Also

stats::sd()

Examples

#----------------------------------------------------------------------------
# fsd() example
#----------------------------------------------------------------------------
library(bkbase)

fsd(1:3)
fsd(c(1:3, NA))

Fast string wrapping

Description

Wrap each element of a character vector to a target width. CRLF/CR are normalized to LF when present and existing newlines may be preserved. Internal runs of whitespace are collapsed to single spaces between words.

Usage

fstr_wrap(x, width = 72L, indent = 0L, exdent = 0L, keep_newlines = FALSE)

fstrwrap(x, width = 72L, indent = 0L, exdent = 0L, keep_newlines = FALSE)

Arguments

x

(character vector)
The text to wrap.

width

(Scalar numeric: 72L; ⁠[1, .Machine$integer.max]⁠)
Target column width in characters for wrapping, including the cost of any indent or exdent.

indent

(Scalar numeric: 0L; ⁠[0, .Machine$integer.max]⁠)
Number of leading spaces to prepend to the first line of each wrapped element. If the element does not wrap, the indent is still applied.

exdent

(Scalar numeric: 0L; ⁠[0, .Machine$integer.max]⁠)
Number of leading spaces to prepend to each line after the first. Has no effect if the element does not wrap.

keep_newlines

(Scalar logical: c(FALSE, TRUE))
FALSE (default) collapses all whitespace including newlines into spaces before wrapping. TRUE splits the input at "\n" and wraps each line independently.

Details

Words are defined by splitting on the regular expression ⁠\\s+⁠, and empty tokens are dropped. NA elements are returned as NA_character_. When keep_newlines = TRUE, input is split into lines at "\n", each line is word-wrapped independently, and empty lines are preserved as empty strings.

A greedy algorithm buffers contiguous words and flushes them to the output when adding the next word would exceed the target width. If the entire line fits within the width when accounting for indent, the line is returned unwrapped. Long words are not broken; they are placed on a line even if they exceed the width. Line length is computed as the sum of the prefix and buffered words plus inter-word spaces.

Names on the input vector are preserved on the output. The result for each element is a single string with any inserted wraps represented by "\n".

Value

Character vector of the same length as x.

See Also

base::strwrap()

Examples

#----------------------------------------------------------------------------
# fstr_wrap()
#----------------------------------------------------------------------------
library(bkbase)

# Basic wrapping
txt <- "This is a simple example sentence that will be wrapped."
cat(fstr_wrap(txt, width = 20))

# Indent for the first line and exdent for continuation lines
txt <- "Indented wrapping across multiple lines of text."
cat(fstr_wrap(txt, width = 20, indent = 2, exdent = 4))

# Existing newlines are preserved and each line is wrapped independently
txt <- "First line that is somewhat long.\nSecond line that is also long."
cat(fstr_wrap(txt, width = 25, exdent = 2))

txt <- "This is a sentence.
Next is the second sentence.
Finally, the third sentence."
cat(fstr_wrap(txt, keep_newlines = FALSE))
cat(fstr_wrap(txt, keep_newlines = TRUE))

# Names preserved and NA propagated
txt <- c(a = "short line", b = NA_character_)
fstr_wrap(txt, width = 25)

Fast tabulate

Description

Calculates the number of times each unique element occurs after excluding missing values. A fast, generalized alternative to base::tabulate().

Usage

ftabulate(x, is_sorted = FALSE)

Arguments

x

(Atomic vector)
The atomic vector for tabulation.

is_sorted

(Scalar logical: FALSE)
Whether or not x is already sorted. Only set is_sorted = TRUE when x is guaranteed to already be sorted.

Details

base::tabulate() only counts positive integers. ftabulate() will count any nonmissing element type.

Value

Integer vector

See Also

base::tabulate(), base::table()

Examples

#----------------------------------------------------------------------------
# ftabulate() example
#----------------------------------------------------------------------------
library(bkbase)

x <- sample(1:10, size = 100, replace = TRUE)
ftabulate(x)
tabulate(x)
table(x)

Fast variance

Description

Calculates the variance after excluding missing values. A fast, unsafe alternative to stats::var(x, na.rm = TRUE).

Usage

fvar(x)

Arguments

x

(numeric)
The numeric vector to calculate the variance.

Value

Scalar numeric

See Also

stats::var()

Examples

#----------------------------------------------------------------------------
# fvar() example
#----------------------------------------------------------------------------
library(bkbase)

fvar(1:3)
fvar(c(1:3, NA))

String interpolation

Description

Expressions enclosed by delimiters will be evaluated or extracted and inserted into the string.

Usage

glue2(
  ...,
  .env = parent.frame(),
  .open = "{",
  .close = "}",
  .sep = " ",
  .eval = TRUE
)

Arguments

...

(character)
One or more strings or character vectors to format. All inputs are coerced with as.character() and joined with .sep into a single template string.

.env

(environment, list, or data.frame: base::parent.frame())
The object used to evaluate expressions or get named values.

.open, .close

(one-character string: "{" and "}")
The opening and closing delimiters of the expressions.

.sep

(string: " ")
The separator used for concatenating strings in ...

.eval

(Scalar logical: c(TRUE, FALSE))
If TRUE (default), the expressions in ... are treated as R code and evaluated. If FALSE, expressions in ... will be treated as variable names in .env (this is faster than evaluation).

Value

Character vector

Author(s)

This function was modified from code by Posit (MIT license) and Mike Cheng (MIT license)

References

https://github.com/tidyverse/glue/blob/main/R/glue.R

https://github.com/coolbutuseless/gluestick/blob/main/R/gluestick.R

See Also

glue::glue()

Examples

#----------------------------------------------------------------------------
# glue2() examples
#----------------------------------------------------------------------------
library(bkbase)

# Extract value from data object
data <- list(name = "Fred")
glue2("Hello {name}", .env = data)

# Extract value from parent.frame()
name <- "Fred"
glue2("Hello {name}")

# A vector is returned if expressions contain vectors
glue2("Number {1:2}")

# Evaluate expression
year_current <- as.numeric(format(Sys.Date(),'%Y'))
year_past <- 1970
glue2(
  "Today is {Sys.Date()}",
  "and it has been {year_current - year_past} years since 1970.",
  .eval = TRUE
)

Is object an atomic vector

Description

Returns TRUE when x is an atomic vector of type integer, double, character, logical, complex, or raw and has no dim attribute.

Usage

is_atomic(x)

Arguments

x

(any object)
The object to be tested.

Details

This is a stricter alternative to base::is.atomic().

Only integer, double, character, logical, complex, and raw vectors return TRUE.

A dim attribute makes the result FALSE. Matrices and arrays therefore return FALSE even when their underlying type is allowed.

The test uses base::typeof(), so classed objects built on an allowed type return TRUE. This includes Date, POSIXct, and factor objects. Objects stored as lists return FALSE, including data.frame and POSIXlt.

NULL returns FALSE. Zero-length vectors of an allowed type return TRUE.

Value

Scalar logical.

See Also

base::is.atomic()

Examples

#----------------------------------------------------------------------------
# is_atomic() examples
#----------------------------------------------------------------------------
library(bkbase)

is_atomic(1)
is_atomic(FALSE)
is_atomic(c("a", "b"))
is_atomic(integer(0))
is_atomic(raw(1))

# FALSE because of a dim attribute
is_atomic(matrix(1))

# FALSE because the object is stored as a list
is_atomic(data.frame(1))

Is vector constant

Description

Returns TRUE if x is a one-dimensional atomic vector where every element is equal to the first element. Zero-length and length-one vectors are constant.

Usage

is_const(x)

Arguments

x

(atomic vector)
The vector to be tested.

Details

NA and NaN are treated as values rather than unknown comparison results. This means c(NA, NA) and c(NaN, NaN) are constant, while c(NA, NaN) and c(1, NA) are not constant.

Non-atomic objects and objects with dimensions return FALSE.

Value

Scalar logical.

See Also

base::match(), base::anyNA()

Examples

#----------------------------------------------------------------------------
# is_const() examples
#----------------------------------------------------------------------------
library(bkbase)

is_const(c(1, 1, 1))
is_const(c(1, 2, 1))

is_const(c(NA, NA))
is_const(c(NaN, NaN))
is_const(c(NA, NaN))

is_const(integer(0))
is_const(NULL)

is_const(matrix(1, nrow = 1))
is_const(list(1, 1))

Is object class date

Description

Returns TRUE if x is a date (class Date).

Usage

is_date(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_date() examples
#----------------------------------------------------------------------------
library(bkbase)

d <- as.Date("2019-01-01")
dt <- as.POSIXct("2019-01-01")
is_datetime(d)
is_datetime(dt)

Is object class date or datetime

Description

Returns TRUE if x is a date (class Date) or datetime (class POSIXct).

Usage

is_date_or_datetime(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_date_or_datetime() examples
#----------------------------------------------------------------------------
library(bkbase)

d <- as.Date("2019-01-01")
dt <- as.POSIXct("2019-01-01")
is_date_or_datetime(d)
is_date_or_datetime(dt)

Is object class datetime

Description

Returns TRUE if x is a datetime (class POSIXct).

Usage

is_datetime(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_datetime() examples
#----------------------------------------------------------------------------
library(bkbase)

dt <- as.POSIXct("2019-01-01")
d <- as.Date("2019-01-01")
is_datetime(dt)
is_datetime(d)

Is object a factor vector

Description

Returns TRUE if x inherits from class "factor".

Usage

is_factor(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_factor() examples
#----------------------------------------------------------------------------
library(bkbase)

is_factor(factor(c("a", "b")))
is_factor(factor("a", ordered = TRUE))
is_factor(factor())
is_factor("a")
is_factor(NULL)

Is object a formula

Description

Returns TRUE if x inherits from class "formula".

Usage

is_formula(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_formula() examples
#----------------------------------------------------------------------------
library(bkbase)

is_formula(1:4)
is_formula("y ~ x")
is_formula(y ~ x)

Is vector monotonically decreasing

Description

Returns TRUE if all values in a x are monotonically decreasing. Returns FALSE for non-numeric input, NULL, and zero-length vectors.

Usage

is_monotonic_decreasing(x, na.rm = FALSE)

Arguments

x

(numeric)
The vector to be tested.

na.rm

(scalar logical)
Whether or not to remove/ignore missing values from x.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_monotonic_decreasing() examples
#----------------------------------------------------------------------------
library(bkbase)

is_monotonic_decreasing(10:-10)
is_monotonic_decreasing(c(3.5, 2, 2, 1, 1, 0))
is_monotonic_decreasing(1)

is_monotonic_decreasing(1:3)

is_monotonic_decreasing(c(3:1, NA))
is_monotonic_decreasing(c(3:1, NA), na.rm = TRUE)

is_monotonic_decreasing(NA_real_)
is_monotonic_decreasing(NA_real_, na.rm = TRUE)

is_monotonic_decreasing(numeric(0L))
is_monotonic_decreasing(NULL)

Is vector monotonically increasing

Description

Returns TRUE if all values in a x are monotonically increasing. Returns FALSE for non-numeric input, NULL, and zero-length vectors.

Usage

is_monotonic_increasing(x, na.rm = FALSE)

Arguments

x

(numeric)
The vector to be tested.

na.rm

(scalar logical)
Whether or not to remove/ignore missing values from x.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_monotonic_increasing() examples
#----------------------------------------------------------------------------
library(bkbase)

is_monotonic_increasing(-10:10)
is_monotonic_increasing(c(0, 1, 1, 2, 2, 3.5))
is_monotonic_increasing(1)

is_monotonic_increasing(3:1)

is_monotonic_increasing(c(1:3, NA))
is_monotonic_increasing(c(1:3, NA), na.rm = TRUE)

is_monotonic_increasing(NA_real_)
is_monotonic_increasing(NA_real_, na.rm = TRUE)

is_monotonic_increasing(numeric(0L))
is_monotonic_increasing(NULL)

Is object a vector of probabilities

Description

Returns TRUE if all values in x are probabilities. A probability is a nonmissing numeric value bounded by [0, 1].

Usage

is_probability(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_probability() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_probability(c(0, 0.5, 1))
is_probability(1L)

# FALSE
is_probability(1.1)
is_probability(NA_real_)
is_probability(numeric(0L))
is_probability(NULL)

Is object a scalar character vector

Description

Returns TRUE if x is a scalar character (character vector of length 1).

Usage

is_scalar_character(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_character() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_scalar_character("a")
is_scalar_character(NA_character_)

# FALSE
is_scalar_character(c("a", "b"))
is_scalar_character(character(0L))
is_scalar_character(1L)
is_scalar_character(NULL)

Is object a scalar date

Description

Returns TRUE if x is a scalar date (class Date of length 1).

Usage

is_scalar_date(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_date() examples
#----------------------------------------------------------------------------
library(bkbase)

is_scalar_date(as.Date("2024-01-01"))
is_scalar_date(as.POSIXct("2024-01-01"))

is_scalar_date(as.Date(c("2024-01-01", "2024-01-02")))
is_scalar_date(as.POSIXct(c("2024-01-01", "2024-01-02")))

Is object a scalar date or datetime

Description

Returns TRUE if x is a scalar date or datetime (class Date or POSIXct of length 1).

Usage

is_scalar_date_or_datetime(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_date_or_datetime() examples
#----------------------------------------------------------------------------
library(bkbase)

is_scalar_date_or_datetime(as.Date("2024-01-01"))
is_scalar_date_or_datetime(as.POSIXct("2024-01-01"))

is_scalar_date_or_datetime(as.Date(c("2024-01-01", "2024-01-02")))
is_scalar_date_or_datetime(as.POSIXct(c("2024-01-01", "2024-01-02")))

Is object a scalar datetime

Description

Returns TRUE if x is a scalar datetime (class POSIXct of length 1).

Usage

is_scalar_datetime(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_datetime() examples
#----------------------------------------------------------------------------
library(bkbase)

is_scalar_datetime(as.Date("2024-01-01"))
is_scalar_datetime(as.POSIXct("2024-01-01"))

is_scalar_datetime(as.Date(c("2024-01-01", "2024-01-02")))
is_scalar_datetime(as.POSIXct(c("2024-01-01", "2024-01-02")))

Is object a scalar double-precision vector

Description

Returns TRUE if x is a scalar double (double-precision vector of length 1).

Usage

is_scalar_double(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_double() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_scalar_double(0)
is_scalar_double(1.5)
is_scalar_double(NA_real_)

# FALSE
is_scalar_double(1L)
is_scalar_double(c(1, 2))
is_scalar_double(numeric(0L))
is_scalar_double(NULL)

Is object a scalar factor vector

Description

Returns TRUE if x is a scalar factor (factor vector of length 1).

Usage

is_scalar_factor(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_factor() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_scalar_factor(factor("a"))
is_scalar_factor(factor("a", ordered = TRUE))
is_scalar_factor(factor(NA))

# FALSE
is_scalar_factor(factor(c("a", "b")))
is_scalar_factor(factor())
is_scalar_factor("a")
is_scalar_factor(NULL)

Is object a scalar integer vector

Description

Returns TRUE if x is a scalar integer (integer vector of length 1).

Usage

is_scalar_integer(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_integer() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_scalar_integer(1L)
is_scalar_integer(NA_integer_)

# FALSE
is_scalar_integer(1)
is_scalar_integer(1:2)
is_scalar_integer(integer(0L))
is_scalar_integer(NULL)

Is object a scalar logical vector

Description

Returns TRUE if x is a scalar logical (logical vector of length 1).

Usage

is_scalar_logical(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_logical() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_scalar_logical(TRUE)
is_scalar_logical(FALSE)
is_scalar_logical(NA)

# FALSE
is_scalar_logical(c(TRUE, FALSE))
is_scalar_logical(logical(0L))
is_scalar_logical(1L)
is_scalar_logical(NULL)

Is object a scalar numeric vector

Description

Returns TRUE if x is a scalar numeric (numeric vector of length 1).

Usage

is_scalar_numeric(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_numeric() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_scalar_numeric(1)
is_scalar_numeric(1L)
is_scalar_numeric(1.5)
is_scalar_numeric(NA_real_)
is_scalar_numeric(NA_integer_)

# FALSE
is_scalar_numeric(1:2)
is_scalar_numeric(numeric(0L))
is_scalar_numeric(NA)
is_scalar_numeric(as.Date("2024-10-01"))
is_scalar_numeric(factor("a"))
is_scalar_numeric(NULL)

Is object a scalar probability

Description

Returns TRUE if x is a scalar probability. A scalar probability is a length 1 nonmissing numeric value bounded by [0, 1].

Usage

is_scalar_probability(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_scalar_probability() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_scalar_probability(0)
is_scalar_probability(0.5)
is_scalar_probability(1)

# FALSE
is_scalar_probability(1.1)
is_scalar_probability(NA_real_)
is_scalar_probability(numeric(0L))
is_scalar_probability(NULL)

Is object a scalar whole number

Description

Returns TRUE if x is a single whole number to some tolerance. See is_scalar_whole_numeric() to test for a scalar whole number without a tolerance. See base::is.integer() to test for integer storage type.

Usage

is_scalar_whole_number(x, tol = 1e-08)

Arguments

x

The object to be tested.

tol

(Scalar numeric: 1e-08; ⁠[0, Inf)⁠)
Absolute differences smaller than tol are ignored, thus assumed to be a whole number.

Details

  • NA, NaN, Inf, and -Inf return FALSE.

  • Zero-length input and NULL return FALSE.

  • Inputs with length other than 1 return FALSE.

Value

Scalar logical

See Also

is_whole_number(), is_scalar_whole_numeric(), base::is.integer()

Examples

#----------------------------------------------------------------------------
# is_scalar_whole_number() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_scalar_whole_number(1L)
is_scalar_whole_number(1)
is_scalar_whole_number(9.0)
is_scalar_whole_number(sqrt(2)^2)
is_scalar_whole_number(1 + 2^-30)
is_scalar_whole_number(1e100)
is_scalar_whole_number(1.00000001)

# FALSE
is_scalar_whole_number(1.0000001)
is_scalar_whole_number(Inf)
is_scalar_whole_number(c(1, 2, 3))

# Missing values and zero-length
is_scalar_whole_number(NA_integer_) # FALSE
is_scalar_whole_number(NA_real_)    # FALSE
is_scalar_whole_number(NaN)         # FALSE
is_scalar_whole_number(numeric(0))  # FALSE
is_scalar_whole_number(NULL)        # FALSE

Is object a scalar whole numeric

Description

Returns TRUE if x is a single integer, or a single double whose value is exactly equal to its truncated form. See is_scalar_whole_number() to test for a scalar whole number within a chosen tolerance. See base::is.integer() to test for integer storage type.

Usage

is_scalar_whole_numeric(x)

Arguments

x

The object to be tested.

Details

  • Inf and -Inf in double storage return TRUE because Inf == trunc(Inf).

  • NA and NaN return FALSE.

  • Zero-length input and NULL return FALSE.

  • Inputs with length other than 1 return FALSE.

Value

Scalar logical

See Also

is_whole_numeric(), is_scalar_whole_number(), base::is.integer()

Examples

#----------------------------------------------------------------------------
# is_scalar_whole_numeric() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_scalar_whole_numeric(1L)
is_scalar_whole_numeric(1)
is_scalar_whole_numeric(9.0)
is_scalar_whole_numeric(1e100)
is_scalar_whole_numeric(Inf)

# FALSE
is_scalar_whole_numeric(1.00000001)
is_scalar_whole_numeric(sqrt(2)^2)
is_scalar_whole_numeric(1 + 2^-30)
is_scalar_whole_numeric(c(1, 2, 3))

# Missing values and zero-length
is_scalar_whole_numeric(NA_integer_) # FALSE
is_scalar_whole_numeric(NA_real_)    # FALSE
is_scalar_whole_numeric(NaN)         # FALSE
is_scalar_whole_numeric(numeric(0))  # FALSE
is_scalar_whole_numeric(NULL)        # FALSE

Is vector strictly decreasing

Description

Returns TRUE if all values in x are strictly decreasing. Returns FALSE for non-numeric input, NULL, and zero-length vectors.

Usage

is_strict_decreasing(x, na.rm = FALSE)

Arguments

x

(numeric)
The vector to be tested.

na.rm

(scalar logical)
Whether or not to remove/ignore missing values from x.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_strict_decreasing() examples
#----------------------------------------------------------------------------
library(bkbase)

is_strict_decreasing(10:-10)
is_strict_decreasing(c(3.5, 2, 2, 1, 1, 0))
is_strict_decreasing(1)

is_strict_decreasing(1:3)

is_strict_decreasing(c(3:1, NA))
is_strict_decreasing(c(3:1, NA), na.rm = TRUE)

is_strict_decreasing(NA_real_)
is_strict_decreasing(NA_real_, na.rm = TRUE)

is_strict_decreasing(numeric(0L))
is_strict_decreasing(NULL)

Is vector strictly increasing

Description

Returns TRUE if all values in x are strictly increasing. Returns FALSE for non-numeric input, NULL, and zero-length vectors.

Usage

is_strict_increasing(x, na.rm = FALSE)

Arguments

x

(numeric)
The vector to be tested.

na.rm

(scalar logical)
Whether or not to remove/ignore missing values from x.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_strict_increasing() examples
#----------------------------------------------------------------------------
library(bkbase)

is_strict_increasing(-10:10)
is_strict_increasing(c(0, 1, 1, 2, 2, 3.5))
is_strict_increasing(1)

is_strict_increasing(3:1)

is_strict_increasing(c(1:3, NA))
is_strict_increasing(c(1:3, NA), na.rm = TRUE)

is_strict_increasing(NA_real_)
is_strict_increasing(NA_real_, na.rm = TRUE)

is_strict_increasing(numeric(0L))
is_strict_increasing(NULL)

Is object a string

Description

Returns TRUE if x is a string (character vector of length 1).

Usage

is_string(x)

Arguments

x

The object to be tested.

Value

Scalar logical

Examples

#----------------------------------------------------------------------------
# is_string() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_string("a")
is_string(NA_character_)

# FALSE
is_string(c("a", "b"))
is_string(character(0L))
is_string(1L)
is_string(NULL)

Is object a vector of whole numbers

Description

Returns TRUE if x consists of whole numbers to some tolerance. See is_whole_numeric() to test for whole numbers without a tolerance. See base::is.integer() to test for integer storage type.

Usage

is_whole_number(x, tol = 1e-08)

Arguments

x

The object to be tested.

tol

(Scalar numeric: 1e-08; ⁠[0, Inf)⁠)
Absolute differences smaller than tol are ignored, thus assumed to be a whole number.

Details

  • NA, NaN, Inf, and -Inf return FALSE.

  • Zero-length input and NULL return FALSE.

Value

Scalar logical

See Also

is_whole_numeric(), is_scalar_whole_number(), base::is.integer()

Examples

#----------------------------------------------------------------------------
# is_whole_number() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_whole_number(1L)
is_whole_number(1)
is_whole_number(9.0)
is_whole_number(sqrt(2)^2)
is_whole_number(1 + 2^-30)
is_whole_number(1e100)
is_whole_number(1.00000001)

# FALSE
is_whole_number(1.0000001)
is_whole_number(Inf)

# Missing values and zero-length
is_whole_number(NA_integer_) # FALSE
is_whole_number(NA_real_)    # FALSE
is_whole_number(NaN)         # FALSE
is_whole_number(numeric(0))  # FALSE
is_whole_number(NULL)        # FALSE

Is object a vector of whole numerics

Description

Returns TRUE if x is an integer vector, or a double vector whose values are exactly equal to their truncated form. See is_whole_number() to test for whole numbers within a chosen tolerance. See base::is.integer() to test for integer storage type.

Usage

is_whole_numeric(x)

Arguments

x

The object to be tested.

Details

  • Inf and -Inf in double storage return TRUE because Inf == trunc(Inf).

  • NA and NaN return FALSE.

  • Zero-length input and NULL return FALSE.

Value

Scalar logical

See Also

is_whole_number(), is_scalar_whole_numeric(), base::is.integer()

Examples

#----------------------------------------------------------------------------
# is_whole_numeric() examples
#----------------------------------------------------------------------------
library(bkbase)

# TRUE
is_whole_numeric(1L)
is_whole_numeric(1)
is_whole_numeric(9.0)
is_whole_numeric(1e100)
is_whole_numeric(Inf)

# FALSE
is_whole_numeric(1.00000001)
is_whole_numeric(sqrt(2)^2)
is_whole_numeric(1 + 2^-30)

# Missing values and zero-length
is_whole_numeric(NA_integer_) # FALSE
is_whole_numeric(NA_real_)    # FALSE
is_whole_numeric(NaN)         # FALSE
is_whole_numeric(numeric(0))  # FALSE
is_whole_numeric(NULL)        # FALSE

Clean lists

Description

Recursively remove NULL and zero-length elements from a list.

Usage

list_clean(x)

Arguments

x

(list)
A list to clean. If x is not a list, it is returned unchanged.

Value

If inherits(x, "list") is FALSE (for example, a data.frame, an atomic vector, NULL, or any S3 object whose class vector does not contain "list"), x is returned unchanged. Otherwise, a list is returned with NULL, zero-length, and recursively-empty elements removed at every level of nesting.

Examples

#----------------------------------------------------------------------------
# list_clean() examples
#----------------------------------------------------------------------------
library(bkbase)

# Removes NULL and zero-length elements, preserves names
x <- list(a = 1, b = NULL, c = logical(0L), d = 2)
list_clean(x)

# Recursive cleaning, including fully-empty sublists
y <- list(a = list(1, NULL), b = list(NULL, logical(0L)))
list_clean(y)

# Non-list inputs are returned unchanged
list_clean(data.frame(x = 1:3))
list_clean(1:5)
list_clean(NULL)

Flatten a nested list to a single level

Description

Recursively flattens any nested lists into a single-level list. Non-list objects are treated as leaves and kept as single elements. If preserve_df = TRUE, data.frames are treated as leaves and not exploded.

Usage

list_flatten2(x, preserve_df = TRUE, keep_names = TRUE)

Arguments

x

(list)
A possibly nested list that should be flattened.

preserve_df

(Scalar logical)
If TRUE (default), data.frames are treated as leaves and not flattened inside.

keep_names

(Scalar logical)
If TRUE (default), names of leaf elements are retained.

Value

A single-level list containing all leaf elements from x, in left-to-right order.

Examples

#----------------------------------------------------------------------------
# list_flatten2() examples
#----------------------------------------------------------------------------
library(bkbase)

# Flatten
x <- list(1, list(2, list(3, 4)), 5)
list_flatten2(x)

# Preserves leaf names and data frames as leaves
y <- list(list(a = 1:2), data.frame(x = 1:2), list(b = "z"))
list_flatten2(y)

# Drop leaf names
z <- list(list(a = c("name1" = 1, "name2" = 2)), list(b = "z"))
list_flatten2(z, keep_names = FALSE)

Convert logical values to 0/1

Description

Converts logical vectors and matrices to integer type. Values FALSE, TRUE, and NA are converted to 0, 1, for NA_integer_, respectively.

Usage

logical_to_integer(x)

Arguments

x

(logical vector, matrix, or array)
The logical object to convert to 0/1 integer.

Details

logical_to_integer() will not drop dimensional attributes (as done by as.integer()).

Value

integer vector, matrix, or array with the same dimensions as x.

Examples

#----------------------------------------------------------------------------
# logical_to_integer() examples
#----------------------------------------------------------------------------
library(bkbase)

logical_to_integer(c(TRUE, FALSE, NA))
logical_to_integer(matrix(c(TRUE, FALSE, TRUE), nrow = 3))

Argument matching

Description

Wraps base::match.call() with two additions.

  1. Argument n selects a call further up the call stack rather than the immediate caller.

  2. Argument defaults = TRUE inserts formal defaults for arguments the caller did not supply.

Usage

match.call2(
  n = 0L,
  definition = sys.function(sys.parent(n + 1L)),
  call = sys.call(sys.parent(n + 1L)),
  expand.dots = TRUE,
  envir = parent.frame(n + 2L),
  defaults = FALSE
)

Arguments

n

(Scalar integer: 0L)
How far up the call stack to match a call. n=0 is defined as the call above match.call2(). Values larger than the available call stack depth raise an error.

definition

(function: sys.function(sys.parent(n + 1L)))
The function whose call is being matched. By default, this is the function n frames above match.call2().

call

(call: sys.call(sys.parent(n + 1L)))
An unevaluated call to the function specified by definition. By default, this is the call n frames above match.call2().

expand.dots

(Scalar logical: c(TRUE, FALSE))
Whether arguments matching ... are expanded into the call as named arguments (TRUE), or kept grouped under a single ... slot (FALSE).

envir

(environment: parent.frame(n + 2L))
The environment used to look up ... when call contains a literal ... symbol. This applies, for example, when a wrapper forwards ... to definition. By default, this is the environment in which definition was called.

defaults

(Scalar logical: c(FALSE, TRUE))
Whether or not to include unspecified default arguments in the call. Formals without a default value are not inserted.

Value

An object of class call. When defaults = TRUE, formal arguments with defaults that the caller did not supply are inserted into the call as unevaluated expressions. Caller-supplied arguments retain their positions, and the inserted defaults are appended after them in formal order.

See Also

base::match.call()

Examples

#----------------------------------------------------------------------------
# match.call2() examples
#----------------------------------------------------------------------------
library(bkbase)

# Basic usage: capture the matched call from within a function.
fit <- function(x, y, method = "ols", tol = 1e-8) {
  match.call2()
}
fit(1:5, 6:10)

# defaults = TRUE inserts unevaluated formal defaults for arguments the
# caller did not supply, producing a self-describing call useful for
# logging or reproducing results.
fit2 <- function(x, y, method = "ols", tol = 1e-8) {
  match.call2(defaults = TRUE)
}
fit2(1:5, 6:10)
fit2(1:5, 6:10, method = "ridge")

# n > 0 reaches further up the call stack, so a helper can inspect how
# its caller was invoked.
log_caller <- function() match.call2(n = 1)
wrapper <- function(a, b = 2) log_caller()
wrapper(a = 10)

# expand.dots = FALSE keeps the ... arguments grouped under one slot.
inspect <- function(x, ...) match.call2(expand.dots = FALSE)
inspect(x = 1, extra1 = "a", extra2 = "b")

Middle sorted element

Description

Return the middle element of an atomic vector after sorting. Missing values are automatically removed.

Usage

middle(x)

Arguments

x

An atomic vector.

Details

For odd-length input, returns the unique middle element of the sorted vector. For even-length input, returns the lower of the two middle elements (sort(x)[ceiling(length(x) / 2)]), not the average. This differs from stats::median() and allows middle() to work on any atomic type, including character and factor inputs.

Value

A scalar of the same type as x.

Examples

#----------------------------------------------------------------------------
# middle() example
#----------------------------------------------------------------------------
library(bkbase)

# Odd-length input returns the single middle element
middle(c(1, 2, 3, 4, 5))

# Even-length input returns the lower of the two middle elements
middle(c(1, 2, 3, 4))

# Works on any atomic type
middle(c("a", "b", "c", "d", "e"))

# Missing values are removed before selecting the middle element
middle(c(1, 2, 3, NA, NA))

Logical OR with NA tolerance

Description

Compute a position-wise logical OR across multiple logical inputs. When no TRUE is present, it allows up to a specified fraction of missing values per position before returning NA.

Usage

or(..., .na_allowed = 0.2)

Arguments

...

Logical vectors of equal length, or a single logical matrix/data.frame. Matrix/data.frame inputs must have at least one column. Inputs are coerced to logical via as.logical, preserving NA.

.na_allowed

(Scalar numeric: 0.2; ⁠[0, 1]⁠)
Maximum allowed fraction of NA per position before the result is set to NA when no TRUE is present.

Details

Standard logical disjunction over multiple vectors (e.g., x | y | z). Each output position corresponds to one vector index, or to one row when a matrix or data.frame is supplied. Returns TRUE for a position if at least one element is TRUE, regardless of missing values. Returns NA for a position if no TRUE is present and the fraction of NA exceeds .na_allowed. Otherwise, missing values are treated as FALSE when evaluating the OR.

For each position (row) ii across pp inputs, let mim_i be the number of NAs and tit_i be the number of TRUEs. Define the missing fraction ri=mi/pr_i = m_i / p. Then:

or_nai={TRUE,if ti1,NA,if ti=0 and ri>.na_allowed,FALSE,if ti=0 and ri.na_allowed.\text{or\_na}_i = \begin{cases} \text{TRUE}, & \text{if } t_i \ge 1, \\ \mathrm{NA}, & \text{if } t_i = 0 \text{ and } r_i > \text{.na\_allowed}, \\ \text{FALSE}, & \text{if } t_i = 0 \text{ and } r_i \le \text{.na\_allowed}. \end{cases}

Notes:

  1. When .na_allowed = 0, behavior matches strict OR: NA propagates only when no TRUE is present.

  2. When .na_allowed=1\text{.na\_allowed} = 1, missingness never forces NA. NAs are treated as FALSE, so the result is TRUE iff any TRUE is present, otherwise FALSE.

Value

A logical vector with values TRUE, FALSE, or NA per the rule in Details.

See Also

base::Logic

Examples

#----------------------------------------------------------------------------
# or() examples
#----------------------------------------------------------------------------
library(bkbase)

x <- c(FALSE, FALSE, FALSE, TRUE,  FALSE)
y <- c(FALSE, FALSE, NA,    FALSE, NA)
z <- c(FALSE, NA,    NA,    NA,    TRUE)

# Base R strict OR
x | y | z

# NA tolerance at 20%
or(x, y, z, .na_allowed = 0.2)

# NA tolerance at 40%
or(x, y, z, .na_allowed = 0.4)

# Single data.frame input
df <- data.frame(x = x, y = y, z = z)
or(df, .na_allowed = 0.4)

# TRUE dominates even when NA is present
or(TRUE, NA, .na_allowed = 0)

Suppress printed output

Description

Output written to stdout during the evaluation of x are suppressed. Messages, warnings, and errors are not suppressed.

Usage

quiet(x)

Arguments

x

An expression.

Value

The value of x, returned invisibly.

See Also

base::suppressMessages()

Examples

#----------------------------------------------------------------------------
# quiet() examples
#----------------------------------------------------------------------------
library(bkbase)

bad_fun <- function(x) {
  cat("Unwanted output\n")
  x
}

# Direct call writes to stdout and returns the value:
bad_fun(2)

# Wrapped call suppresses stdout and returns invisibly:
quiet(bad_fun(2))

# The return value is preserved:
result <- quiet(bad_fun(2))
result

Random sample

Description

base::sample() treats a single numeric x with x >= 1 as 1:x and samples from that sequence. This surprises callers when x may have varying length, such as in sample(x). resample() always samples from the elements of x itself. See base::sample() for more details.

Usage

resample(x, size, replace = FALSE, prob = NULL)

Arguments

x

(Atomic vector)
The atomic vector to sample from.

size

(Scalar integer: ⁠[1, Inf)⁠)
The number of elements to sample.

replace

(Scalar logical)
Whether or not sampling should be done with replacement.

prob

(numeric: NULL)
A non-negative numeric vector of length length(x) whose elements sum to 1. Element prob[i] is the probability of sampling x[i]. NA values are not allowed.

Details

When replace = FALSE, size must not exceed length(x).

Value

A vector of length size with elements sampled from x.

See Also

base::sample()

Examples

#----------------------------------------------------------------------------
# resample() examples
#----------------------------------------------------------------------------
library(bkbase)

set.seed(2)

# Sample without replacement
resample(x = 1:10, size = 5)

# Sample with replacement
resample(x = c("a", "b", "c"), size = 5, replace = TRUE)

# Weighted sampling
resample(
  x = c("heads", "tails"),
  size = 3, replace = TRUE,
  prob = c(0.7, 0.3)
)

# A length-1 vector is sampled as-is, unlike base::sample()
resample(x = 5L, size = 1L)
sample(x = 5L, size = 1L) # samples from 1:5 instead

Reset data frame row names

Description

Quickly reset data frame row names to integers using a pipe-compatible function.

Usage

reset_rownames(data)

remove_rownames(data)

Arguments

data

(data.frame)
The data frame whose row names should be reset.

Value

A data frame identical to data except that the row.names attribute is reset to 1:nrow(data).

Examples

#----------------------------------------------------------------------------
# reset_rownames() examples
#----------------------------------------------------------------------------
library(bkbase)

# Subsetting a data frame preserves the original row names.
df <- data.frame(a = 1:5)
sub <- df[c(3, 5), , drop = FALSE]
sub

# reset_rownames() renumbers them as 1:nrow(sub).
reset_rownames(sub)

# remove_rownames() is an alias for reset_rownames().
remove_rownames(sub)

# Pipe-compatible.
df[c(3, 5), , drop = FALSE] |> reset_rownames()

Run length encoding

Description

Returns the lengths and values of runs of consecutive equal elements in a vector.

Usage

rle2(x, order = FALSE, index = TRUE, na.last = TRUE)

Arguments

x

(Atomic vector)
The vector to be run length encoded.

order

(Scalar logical)
Whether or not to order the data frame based on the values in x.

index

(Scalar logical)
Whether or not to add the index position for each run/consecutive value in columns named 'start' and 'stop'.

na.last

(Scalar logical: TRUE)
Controls placement of NA runs when order = TRUE. TRUE puts them last, FALSE puts them first, NA drops them. Ignored when order = FALSE.

Details

base::rle() returns a list with a custom print method. rle2() returns a data.frame, optionally annotated with the start and stop indices of each run, and optionally sorted by value.

Unlike base::rle(), consecutive NAs collapse into a single run. A transition between NA and a non-NA value also counts as a run boundary.

A zero-length x returns a zero-row data.frame with the documented columns.

The returned data.frame is not compatible with base::inverse.rle().

Value

data.frame with structure:

Column Name Class Note
1 value class(x)
2 length integer
3 start integer Optional
4 stop integer Optional

See Also

base::rle()

Examples

#----------------------------------------------------------------------------
# rle2() examples
#----------------------------------------------------------------------------
library(bkbase)

x <- c(NA, NA, rev(rep(6:10, 1:5)), NA)

# base::rle() splits NAs into single-element runs and returns a list.
rle(x)

# rle2() collapses consecutive NAs and returns a data frame.
rle2(x)

# Drop the start and stop columns.
rle2(x, index = FALSE)

# Sort by value. NA runs are placed last by default.
rle2(x, order = TRUE)

# Sort by value and drop NA runs entirely.
rle2(x, order = TRUE, na.last = NA)

# Works on any atomic vector, including character.
rle2(c("a", "a", "b", "a", "a", "a"))

Remove missing values

Description

Remove missing values from an atomic vector using a pipe-compatible function.

Usage

rm_na(x)

rmna(x)

Arguments

x

(vector)
The vector to remove missing values from.

Details

  • NaN values are also removed because is.na(NaN) returns TRUE.

  • NULL input returns NULL because anyNA(NULL) is FALSE.

  • Zero-length input is returned unchanged.

  • Attributes such as names, factor levels, and Date/POSIXct class are preserved by the [ subset.

Value

A vector of the same type and class as x with NA values removed.

See Also

stats::na.omit(), as_na()

Examples

#----------------------------------------------------------------------------
# rm_na() examples
#----------------------------------------------------------------------------
library(bkbase)

# No NAs: input is returned unchanged
rm_na(1:3)

# NAs are removed
rm_na(c(1, NA, 2, NA, 3))

# NaN is also removed
rm_na(c(1, NaN, 2))

# Names and other attributes are preserved
rm_na(c(a = 1, b = NA, c = 3))
rm_na(factor(c("a", NA, "b")))

# rmna() is an alias for rm_na()
c(1, NA, 2) |> rmna()

Round mixed-type numbers

Description

Round the numeric elements of an atomic vector and return a character vector. Elements that do not represent a single number are left unchanged.

Usage

round2(x, digits = 3L)

Arguments

x

(atomic vector)
The vector whose numeric elements should be rounded.

digits

(scalar whole number: 3L)
The number of decimal places for rounded numbers. Must be finite.

Details

Each element is coerced to character, then parsed with base::as.numeric(). Elements that parse to a finite number or to Inf/-Inf are rounded to digits decimal places. All other elements pass through unchanged, including text such as "$99.99", "NaN", and NA.

A nonzero value that rounds to zero loses all magnitude information. Such values are shown in compact scientific notation (for example "1.0e-04") instead of "0". Exact zero is returned as "0".

Logical input is rendered as "TRUE"/"FALSE" rather than 0/1. Names on x are preserved.

Value

A character vector the same length as x.

See Also

base::round(), base::sprintf()

Examples

#----------------------------------------------------------------------------
# round2() example
#----------------------------------------------------------------------------
library(bkbase)

round2(c("hello", "0.0001", "1.23456", "hello 1.23456"))

Row-wise maxima

Description

Compute row-wise maxima from a logical/numeric matrix or data.frame. Optionally ignore missing values. Row names are preserved on ordinary non-empty results.

Usage

rowMaxs(x, na.rm = FALSE)

Arguments

x

(logical/numeric matrix or data.frame)
A rectangular object whose rows will be aggregated via maxima. Each column must be logical or numeric.

na.rm

(Scalar logical: FALSE; c(FALSE, TRUE))
If TRUE, ignore NA values when computing row-wise maxima, returning NA only when all values in a row are missing. If FALSE, the presence of any NA in a row yields an NA result for that row.

Details

Let pp be the number of columns in x. For row ii, define the row-wise maximum MiM_i as follows.

If na.rm = TRUE, the maximum is computed over the observed values only.

Mi=max{xij:xij not NA}.M_i = \max\{x_{ij} : x_{ij} \text{ not NA}\}.

NaN is treated as missing because missingness is determined by base::is.na(). If all entries in row ii are missing, the returned value for that row is NA.

If na.rm = FALSE, the maximum includes missing values.

Mi=max{xij}.M_i = \max\{x_{ij}\}.

In this case, any NA present in row ii yields an NA result for that row.

Inf and -Inf are treated as observed values and can be returned as row maxima. Logical values are evaluated as FALSE = 0 and TRUE = 1. If x has row names, those names are assigned to the resulting vector.

Value

A vector of length nrow(x) containing the row-wise maxima. The storage type is integer when x is integer or logical, and double otherwise. If x has zero rows, a zero-length vector of the appropriate storage type is returned. If x has zero columns, an unnamed length-nrow(x) vector of NA of the appropriate storage type is returned. Rows return NA according to the rules described by na.rm. For inputs with at least one row and one column, row names are preserved when present.

See Also

Other rowwise: rowMaxs2(), rowMeans2(), rowSums2()

Examples

#----------------------------------------------------------------------------
# rowMaxs() examples
#----------------------------------------------------------------------------
library(bkbase)

# Example matrix
m <- matrix(
  c(1, NA, 3, 4,
    2,  5, NA, 6),
  nrow = 2,
  byrow = TRUE
)
m

# Row-wise maxima without removing NAs (rows containing NA yield NA)
rowMaxs(m, na.rm = FALSE)

# Row-wise maxima removing NAs
rowMaxs(m, na.rm = TRUE)

# Row names are preserved on ordinary non-empty results
rownames(m) <- c("row_a", "row_b")
rowMaxs(m, na.rm = TRUE)

Row-wise maxima with NA allowance

Description

Compute row-wise maxima from a logical/numeric matrix or data.frame. Rows exceeding a specified missing-value proportion are set to NA. Row names are preserved on ordinary non-empty results.

Usage

rowMaxs2(x, na_allowed = 0.2)

Arguments

x

(logical/numeric matrix or data.frame)
A rectangular object whose rows will be aggregated via maxima. Each column must be logical or numeric.

na_allowed

(Scalar numeric: 0.2; ⁠[0, 1]⁠)
Maximum allowed proportion of missing values per row (πi\pi_i) before the result is set to NA. Rows with πi>na_allowed\pi_i > \text{na\_allowed} return NA. Rows with πina_allowed\pi_i \leq \text{na\_allowed} are computed using observed values only.

Details

For row ii, let πi\pi_i be the proportion of missing values in that row.

If πi>τ\pi_i > \tau where τ\tau is na_allowed, the returned maximum for row ii is NA. Otherwise, the maximum is computed over the observed values only:

Mi=max{xij:xij not NA}.M_i = \max\{x_{ij} : x_{ij} \text{ not NA}\}.

If all entries in a row are NA, the result for that row is NA regardless of na_allowed. NaN is treated as missing because missingness is determined by base::is.na(). It counts toward πi\pi_i and is excluded from the maximum. Inf and -Inf are treated as observed values and can be returned as row maxima. Logical values are evaluated as FALSE = 0 and TRUE = 1. If x has row names, those names are assigned to the resulting vector.

Value

A vector of length nrow(x) containing the row-wise maxima, with NA where the missing proportion exceeds na_allowed. The storage type is integer when x is integer or logical, and double otherwise. If x has zero rows, a zero-length vector of the appropriate storage type is returned. If x has zero columns, an unnamed length-nrow(x) vector of NA of the appropriate storage type is returned. For inputs with at least one row and one column, row names are preserved when present.

See Also

Other rowwise: rowMaxs(), rowMeans2(), rowSums2()

Examples

#----------------------------------------------------------------------------
# rowMaxs2() examples
#----------------------------------------------------------------------------
library(bkbase)

# Example matrix
m <- matrix(
  c(1, NA, 3, 4,
    2,  5, NA, 6),
  nrow = 2,
  byrow = TRUE
)
m

# Allow up to 25% missing per row: both rows are computed
rowMaxs2(m, na_allowed = 0.25)

# Tighten allowance to 0%: any row with an NA becomes NA
rowMaxs2(m, na_allowed = 0)

# Row names are preserved on ordinary non-empty results
rownames(m) <- c("row_a", "row_b")
rowMaxs2(m, na_allowed = 0.5)

Row-wise means with NA allowance

Description

Compute row-wise means from a logical/numeric matrix or data.frame. Rows exceeding a specified missing-value proportion are set to NA.

Usage

rowMeans2(x, na_allowed = 0.2, round_digits = NULL)

Arguments

x

(logical/numeric matrix or data.frame)
A rectangular object whose rows will be aggregated via means. Each column must be logical or numeric.

na_allowed

(Scalar numeric: 0.2; ⁠[0, 1]⁠)
Maximum allowed proportion of missing values per row (πi\pi_i) before the result is set to NA. Rows with πi>na_allowed\pi_i > \text{na\_allowed} return NA; rows with πina_allowed\pi_i \le \text{na\_allowed} are computed.

round_digits

(NULL or scalar non-negative integer: NULL)
If not NULL, round the resulting means to the specified number of digits.

Details

Let pp be the number of columns in x. For row ii, let πi\pi_i be the proportion of missing values in that row.

If πi>τ\pi_i > \tau where τ\tau is na_allowed, the returned mean for row ii is NA. Otherwise, when at least one observed value exists, the mean is computed over the observed values only:

Mi=1{j:xij not missing}j:xij not missingxij.M_i = \frac{1}{|\{j : x_{ij} \text{ not missing}\}|} \sum_{j: x_{ij} \text{ not missing}} x_{ij}.

If all entries in a row are NA or NaN, the result for that row is NA regardless of na_allowed. NaN is treated as missing because missingness is determined by base::is.na(). Inf and -Inf are treated as observed values and are passed to base::rowMeans() arithmetic. A row with both observed Inf and -Inf can therefore return NaN. Logical values are averaged as FALSE = 0 and TRUE = 1.

Rounding is disabled by default. Set round_digits to round the resulting means.

Value

A double vector of length nrow(x) containing the row-wise means, with NA where the missing proportion exceeds na_allowed. For inputs with at least one row and one column, row names are preserved. If x has zero rows, a zero-length double vector is returned. If x has zero columns, an unnamed length-nrow(x) double vector of NA is returned.

See Also

Other rowwise: rowMaxs(), rowMaxs2(), rowSums2()

Examples

#----------------------------------------------------------------------------
# rowMeans2() examples
#----------------------------------------------------------------------------
library(bkbase)

m <- matrix(
  c(1, NA, 3, 4,
    2,  5, NA, 6),
  nrow = 2,
  byrow = TRUE
)
m

# Allow up to 25% missing per row
rowMeans2(m, na_allowed = 0.25)

# Enable rounding to 2 digits
rowMeans2(m, na_allowed = 0.5, round_digits = 2)

Row-wise sums with NA allowance

Description

Compute row-wise sums from a logical/numeric matrix or data.frame. Rows exceeding a specified missing-value proportion are set to NA. Optionally impute missing values using the row mean when the proportion of missing values does not exceed the specified threshold.

Usage

rowSums2(x, na_allowed = 0.2, mean_impute = FALSE, round_digits = NULL)

Arguments

x

(logical/numeric matrix or data.frame)
A rectangular object whose rows will be aggregated via sums. Each column must be logical or numeric.

na_allowed

(Scalar numeric: 0.2; ⁠[0, 1]⁠)
Maximum allowed proportion of missing values per row (πi\pi_i) before the result is set to NA. Rows with πi>na_allowed\pi_i > \text{na\_allowed} return NA; rows with πina_allowed\pi_i \le \text{na\_allowed} are computed.

mean_impute

(Scalar logical: FALSE; c(FALSE, TRUE))
Let πi\pi_i be the proportion of missing values in rows. If TRUE, rows with at least one missing value and πina_allowed\pi_i \le \text{na\_allowed} are imputed using the row mean scaled by the number of columns. If FALSE, sums are computed over observed values only.

round_digits

(NULL or scalar non-negative integer: NULL)
If not NULL, round the resulting sums to the specified number of digits.

Details

Let pp be the number of columns in x. For row ii, let πi\pi_i be the proportion of missing values in that row.

If πi>τ\pi_i > \tau where τ\tau is na_allowed, the returned sum for row ii is NA. Otherwise:

Si=j:xij not NAxijS_i = \sum_{j: x_{ij} \text{ not NA}} x_{ij}

when mean_impute = FALSE.

Si=pxˉi,obsS_i = p \cdot \bar{x}_{i,\text{obs}}

when mean_impute = TRUE, where xˉi,obs\bar{x}_{i,\text{obs}} is the mean of the non-missing values in row ii.

If all entries in a row are NA or NaN, the row has no observed mean. With mean_impute = TRUE, such rows return NA even when na_allowed = 1. With mean_impute = FALSE, such rows return 0 when allowed by na_allowed, matching base::rowSums() with na.rm = TRUE. NaN is treated as missing because missingness is determined by base::is.na(). Inf and -Inf are treated as observed values and are passed to base::rowSums() arithmetic. A row with both observed Inf and -Inf can therefore return NaN. Logical values are summed as FALSE = 0 and TRUE = 1.

Rounding is disabled by default. Set round_digits to round the resulting sums.

Value

A double vector of length nrow(x) containing the row-wise sums, with NA where the missing proportion exceeds na_allowed. For inputs with at least one row and one column, row names are preserved. If x has zero rows, a zero-length double vector is returned. If x has zero columns, an unnamed length-nrow(x) double vector of NA is returned.

See Also

Other rowwise: rowMaxs(), rowMaxs2(), rowMeans2()

Examples

#----------------------------------------------------------------------------
# rowSums2() examples
#----------------------------------------------------------------------------
library(bkbase)

m <- matrix(
  c(1, NA, 3, 4,
    2,  5, NA, 6),
  nrow = 2,
  byrow = TRUE
)
m

# No imputation, allow up to 25% missing per row
rowSums2(m, na_allowed = 0.25, mean_impute = FALSE)

# Mean imputation for rows with some missing but within threshold
rowSums2(m, na_allowed = 0.5, mean_impute = TRUE)

# Enable rounding to 0 digits
rowSums2(m, na_allowed = 0.5, mean_impute = TRUE, round_digits = 0)

Nondecreasing integer sequence

Description

Similar to seq.int, but returns an empty vector (integer(0)) if the starting point is larger than the end point.

Usage

seq2(from, to)

Arguments

from

(Scalar integer)
The beginning value of the integer sequence.

to

(Scalar integer)
The ending value of the integer sequence.

Details

Safer than using something like from:to or seq.int in a programming scenario.

Value

Integer vector

See Also

base::seq.int(), base::seq(), base::seq_len(), base::seq_along()

Examples

#----------------------------------------------------------------------------
# seq2() examples
#----------------------------------------------------------------------------
library(bkbase)

seq2(from = 1, to = 5)
seq2(from = 1, to = 1)
seq2(from = 1, to = 0)

Remove whitespace

Description

Removes whitespace from the left and right sides of a string.

Usage

str_trim2(x, whitespace = "[ \t\r\n]")

Arguments

x

(character)
The character vector to remove left and right side whitespace.

whitespace

(string: "[ \t\r\n]")
The regular expression used to match whitespace.

Details

NULL is returned as character(0L).

Value

character vector

See Also

base::trimws()

Examples

#----------------------------------------------------------------------------
# str_trim2() examples
#----------------------------------------------------------------------------
library(bkbase)

x <- " example "
str_trim2(x)

str_trim2(c(" a ", "\tb\n", NA))
str_trim2("--x--", whitespace = "-")