Supplementary utilities and extensions to R that are idiomatic in
style.
You can install the development version of suppr like so:
# install.packages("pak")
pak::pak("LJ-Jenkins/suppr")suppr provides a range of miscellaneous supplementary functions, some of
which are very simple wrappers to save some keystrokes, others address
common tasks, and others provide new functionality to suppr versions of
an existing R functions. All are intended to be idiomatic to R, as
if they were part of the base R packages.
Much of suppr is directly amended from the R source code - all credit
to the authors for their great work!
%''%or%""%- if the lhs is ““, return the rhs, else return the lhs.%!||%- if the lhs isNULL, return the lhs, else return the rhs.%0%- if the lhs is of length0, return the rhs, else return the lhs.%allin%,%anyin%,%nonein%,%onein%and%notin%-base::%in%variants.
"" %''% "a"
#> [1] "a"
NULL %!||% "a"
#> NULL
c() %0% "a"
#> [1] "a"
c("a", "b") %allin% c("a", "b", "c")
#> [1] TRUE
c("a", "d") %anyin% c("a", "b", "c")
#> [1] TRUE
c("a", "d") %nonein% c("a", "b", "c")
#> [1] FALSE
c("a", "d") %onein% c("a", "b", "c")
#> [1] TRUE
c("a", "d") %notin% c("a", "b", "c")
#> [1] FALSE TRUEbckQuote()- backquotes a string.collapse()andcollapse0()- collapse a vector (or vectors) into a single string, optionally ‘recursively’ (in the sense of collapse each argument individually and then collapse the results).listing()- turns a character vector into a human-readable list (in the grammatical sense), optionally with quoting and/or a conjunction like “and” or “or”.cat0()-base::cat()withsep = "".grepf(),grepi(),greplf(),grepli(),grepvf(),grepvi(),subf(),subi(),gsubf()andgsubi()- strongly typed variants ofbase::grep(),base::grepl(),base::grepv(),base::sub()andbase::gsub()for the commonfixed = TRUEandignore.case = TRUEcases.anyZchar()- returns the1-based index of the first zero character element if any, otherwise0.anyWS()- returns the1-based index of the first all whitespace element if any, otherwise0. Optionally, zero character elements can be treated as all whitespace.
bckQuote(c("a", "b"))
#> [1] "`a`" "`b`"
collapse(c("a", "b", "c"))
#> [1] "abc"
listing(c("a", "b", "c"))
#> [1] "a, b and c."
cat0("a", "b", "c")
#> abc
greplf("foo", c("foo", "Foo", "bar"))
#> [1] TRUE FALSE FALSE
grepli("foo", c("foo", "Foo", "bar"))
#> [1] TRUE TRUE FALSE
anyZchar(c("hi", "bye", " ", ""))
#> [1] 4
anyWS(c("hi", "bye", " ", ""))
#> [1] 3checkDots()- version ofbase::chkDots()that can error, not just warn.dotsNames()- returns the names of...arguments, returning all""if unnamed (likemethods::allNames()but without evaluating...).subDots()- substitutes...arguments, returning a list of the substituted expressions.dp1Dots()- substitutes...arguments, before applyingbase::deparse1()to each, returning a character vector of the dot arguments.
f <- function(fn, ...) fn(...)
f(checkDots, a = 1, b = 2)
#> Error:
#> ! In f(checkDots, a = 1, b = 2) :
#> extra named arguments 'a', 'b' are not allowed.
f(dotsNames, 1, 2)
#> [1] "" ""
f(subDots, x = a + b, y = a * b)
#> $x
#> a + b
#>
#> $y
#> a * b
f(dp1Dots, x = a + b, y = a * b)
#> x y
#> "a + b" "a * b"match.argv()- matches function argument input to a list of valid values, not just strings likebase::match.arg().message2(),stop2(),warning2()andstopifnot2()- wrappers forbase::message(),base::stop(),base::warning()andbase::stopifnot()that enable the inclusion of any call on the stack in the error message via a more flexiblecall.argument.warningifnot()- a wrapper forstopifnot2()that produces a warning instead of an error.stopifnot.with()- a wrapper forstopifnot2()that evaluates expressions in a specified environment/data object (likebase::with()).
match.argv(1:3, list(c("a", "b"), list(1:3), 1:3))
#> [1] 1 2 3
f1 <- function(call.) stop2("error", call. = call.)
f2 <- function(call.) f1(call. = call.)
f2(call. = 2)
#> Error in `f2()`:
#> ! error
f1 <- function(call.) stopifnot2(all.equal(1, 2), call. = call.)
f2(call. = 1)
#> Error in `f1()`:
#> ! 1 and 2 are not equal:
#> Mean relative difference: 1
warningifnot(1 == 2, 3 > 4, warn.all = TRUE, call. = FALSE)
#> Warning: 1 == 2 is not TRUE
#> Warning: 3 > 4 is not TRUE
stopifnot.with(data.frame(x = 1, y = 2), x == y)
#> Error:
#> ! with data.frame(x = 1, y = 2) : x == y is not TRUEaddClass()- adds a class/classes to an object, either preserving existing classes (by prepending given classes), or overwriting existing classes, and returning the object.isVector()- wrapper forbase::is.vector()that allows multiple classes to be specified.is.Date(),is.datetype(),is.POSIXt(),is.POSIXct()andis.POSIXlt()- date type predicates.is.boolean(),is.string()andnzstring()- predicates for common scalar values.
x <- structure(1:3, class = c("a", "b"))
class(addClass(x, "my_new_class"))
#> [1] "my_new_class" "a" "b"
isVector(1:3, c("character", "list", "numeric"))
#> [1] TRUE
is.Date(Sys.Date())
#> [1] TRUE
is.datetype(Sys.Date())
#> [1] TRUE
is.POSIXt(Sys.time())
#> [1] TRUE
is.POSIXct(Sys.time())
#> [1] TRUE
is.POSIXlt(Sys.time())
#> [1] FALSE
is.boolean(TRUE)
#> [1] TRUE
is.string("")
#> [1] TRUE
nzstring("")
#> [1] FALSEis.even()andis.odd()- returns logical vector indicating if elements are even or odd, respectively.
is.even(c(-2:2, NA))
#> [1] TRUE FALSE TRUE FALSE TRUE FALSE
is.odd(c(1, 2, NA, Inf), noparity.na = TRUE)
#> [1] TRUE FALSE NA NAwhichMin()andwhichMax()- wrappers forbase::which.min()andbase::which.max()that offer a newlocargument to alternatively return the first, last, or all, minima/maxima.
x <- c(1, 2, 3, 1, 2, 3)
whichMin(x, loc = "first")
#> [1] 1
whichMin(x, loc = "last")
#> [1] 4
whichMin(x, loc = "all")
#> [1] 1 4is.nonfinite()(and aliasis.nf()) - returns a logical vector indicating which elements are non-finite (i.e.,NA,NaN,Infor-Inf).anyNF()- returns the1-based index of the first non-finite value if any, otherwise0.whichNA()- returns the indices ofNAvalues.setNA()- sets given indices toNA.na.vector()- returns a vector ofNAvalues of a given length and type.na.refill()- for an object that has hadNAvalues removed bystats::na.omit(), refill theNAvalues at the original indices, returning an object of the same size as the original.
is.nonfinite(c(1, 2, NA, Inf))
#> [1] FALSE FALSE TRUE TRUE
anyNF(c(1, 2, NA, Inf))
#> [1] 3
whichNA(c(1, 2, NA, Inf))
#> [1] 3
x <- c(1, 2, 3, 4)
setNA(x, c(1, 3))
#> [1] NA 2 NA 4
na.vector(5, type = "character")
#> [1] NA NA NA NA NA
x <- stats::na.omit(c(1, 2, NA, 4))
x
#> [1] 1 2 4
#> attr(,"na.action")
#> [1] 3
#> attr(,"class")
#> [1] "omit"
na.refill(x)
#> [1] 1 2 NA 4
#> attr(,"na.action")
#> [1] 3
#> attr(,"class")
#> [1] "refilled"is.integerish()- returnsTRUEif elements are all ‘integerish’ orFALSEif not.is.whole()andis.wholenumber()- returns a singleTRUE/FALSE, or a logical vector, if elements are all whole numbers or not, respectively.
is.integerish(c(1, 1.000000001))
#> [1] FALSE
is.whole(c(1, 1.000000001))
#> [1] TRUE
is.wholenumber(c(1, 2, 3.5, 4))
#> [1] TRUE TRUE FALSE TRUErepeated()- returns a logical vector indicating which elements are repeated (analogous toduplicated(x, fromLast = FALSE) | duplicated(x, fromLast = TRUE)).whichRepeated()- returns the indices of repeated elements.repeats()- returns repeated elements.
x <- c(1, 2, 3, 1, 2, 3, 4, 5)
repeated(x)
#> [1] TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE
whichRepeated(x)
#> [1] 1 2 3 4 5 6
repeats(x)
#> [1] 1 2 3 1 2 3rm.first()andrm.last()- removes the first or last ‘n’ elements of a vector, respectively.
x <- 1:10
rm.first(x, 3)
#> [1] 4 5 6 7 8 9 10
rm.last(x, 3)
#> [1] 1 2 3 4 5 6 7predapply()- applies a predicate function to each element of a vector, returning a logical vector. Option to reduce the output to a singleTRUEorFALSEvalue.empty.list()- wrapper forvector("list", length)that returns an empty list of a given length.path()- wrapper forbase::file.path()andbase::normalizePath(). Option to specify if the path is on a shared drive, prepending.Platform$file.sepif so.dims()- returns the dimensions of an object, orc(length(x), 0L)if it has no dim attribute.enumerate()- returns a list of lists - one for each element of a vector, with the corresponding positional list containing the vector element, index and name.libraries()andrequires()- wrappers forbase::library()andbase::require()that can load multiple packages at once, either from names, strings, or character vectors.
predapply(1:10, is.even, reduce = "any")
#> [1] TRUE
empty.list(2)
#> [[1]]
#> NULL
#>
#> [[2]]
#> NULL
path("mysd", "mydir", sharedDrive = TRUE, mustWork = FALSE)
#> [1] "\\\\mysd\\mydir"
dims(1:10)
#> [1] 10 0
enumerate(c("a", el = "b"))
#> [[1]]
#> [[1]]$idx
#> [1] 1
#>
#> [[1]]$val
#> [1] "a"
#>
#> [[1]]$name
#> [1] ""
#>
#>
#> [[2]]
#> [[2]]$idx
#> [1] 2
#>
#> [[2]]$val
#> [1] "b"
#>
#> [[2]]$name
#> [1] "el"
libraries(stats, "utils")
x <- c("stats", "utils")
requires(x, "methods", character.only = TRUE)Functions should have similar overhead to their nearest R equivalents.
Most of the ‘data wrangling’ functions (and some others) have been
implemented in C and typically perform equivalently to their R
counterparts.
If you encounter a clear bug, please file an issue with a minimal reproducible example on GitHub.
Please note that the suppr project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.
