Skip to content

Commit

Permalink
Merge pull request #75 from adamlilith/solstice2022_2023
Browse files Browse the repository at this point in the history
Solstice2022 2023
  • Loading branch information
adamlilith committed May 1, 2024
2 parents 23d228f + f752686 commit dfad6e7
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 13 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: omnibus
Type: Package
Title: Helper Tools for Managing Data, Dates, Missing Values, and Text
Version: 1.2.12
Date: 2024-04-06
Version: 1.2.13
Date: 2024-05-01
Authors@R:
c(
person(
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export("%>=%")
export("%>=na%")
export("%>na%")
export("%notin%")
export(appendLists)
export(bracket)
export(capIt)
export(combineDf)
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
omnibus 1.2.X3 (2024-05-01)
===========
o Added `appendLists()` for combining lists with elements that may have the same names
o `roundedSigDigits()` works for numbers expressed in scientific notation

omnibus 1.2.12 (2024-04-06)
===========
o Changed arguments of `mergeLists()` to `...` so it can handle >2 lists at a time
Expand Down
49 changes: 49 additions & 0 deletions R/appendLists.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#' Append values to elements of a list from another list
#'
#' This function "adds" two lists with the same or different names together. For example, if one list is as \code{l1 <- list(a=1, b="XYZ")} and the second is as \code{l2 <- list(a=3, c=FALSE)}, the output will be as \code{list(a = c(1, 3), b = "XYZ", c = FALSE)}. All elements in each list must have names.
#'
#' If two lists share the same name and these elements have the same class, then they will be merged as-is. If the classes are different, one of them will be coerced to the other (see *Examples*). The output will have elements with the names of all lists.
#'
#' @param ... Two or more lists. All elements must have names.
#'
#' @seealso \code{\link{mergeLists}}
#'
#' @returns A \code{list}.
#'
#' @examples
#'
#' # same data types for same named element
#' l1 <- list(a=1, b="XYZ")
#' l2 <- list(a=3, c=FALSE)
#' appendLists(l1, l2)
#'
#' # different data types for same named element
#' l1 <- list(a=3, b="XYZ")
#' l2 <- list(a="letters", c=FALSE)
#' appendLists(l1, l2)
#'
#' @aliases appendLists
#' @rdname appendLists
#' @export
appendLists <- function(...) {

dots <- list(...)

for (i in seq_along(dots)) {
names <- names(dots[[i]])
if (any(is.null(names)) || anyNA(names)) stop("All elements in the list have to have names.")
}

out <- dots[[1L]]
for (i in 2L:length(dots)) {

l1 <- out
l2 <- dots[[i]]
binded <- c(l1, l2)
out <- tapply(binded, names(binded), function(x) unlist(x, FALSE, FALSE))

}

out

}
2 changes: 2 additions & 0 deletions R/mergeLists.r
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#'
#' @returns A list.
#'
#' @seealso \code{\link{appendLists}}
#'
#' @examples
#'
#' list1 <- list(a=1:3, b='Hello world!', c=LETTERS[1:3])
Expand Down
3 changes: 2 additions & 1 deletion R/omnibus.r
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#' @details
#'
#' @section Data manipulation and properties:
#' \code{\link{appendLists}}: Merge lists, appending elements with the same name. \cr
#' \code{\link{bracket}}: Find values that bracket a given number. \cr
#' \code{\link{combineDf}}: Combine data frames with different schema. \cr
#' \code{\link{compareFloat}}: Compare values to floating-point precision. \cr
Expand All @@ -19,7 +20,7 @@
#' \code{\link{maxRuns}}: Maximum number of continuous "runs" of values meeting a particular condition. \cr
#' \code{\link{mirror}}: Flip an object left-right (or up-down). \cr
#' \code{\link{mmode}}: Modal value(s). \cr
#' \code{\link{mergeLists}}: Merge lists. \cr
#' \code{\link{mergeLists}}: Merge lists, with precedence for elements of one list over another if they have the same names. \cr
#' \code{\link{notIn}} and \code{\link[omnibus:notIn]{\%notin\%}}: Opposite of \code{\%in\%}. \cr
#' \code{\link{renumSeq}}: Renumber a sequence. \cr
#' \code{\link{rotateMatrix}}: Rotate a matrix. \cr
Expand Down
5 changes: 3 additions & 2 deletions R/pmatchSafe.r
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,19 @@
#'
#' @export
pmatchSafe <- function(x, table, useFirst = FALSE, error = TRUE, ignoreCase = TRUE, nmax = length(x), ...) {

if (ignoreCase) {

x <- tolower(x)
lowerTable <- tolower(table)
matches <- .pmatchSafe(x, table = lowerTable, useFirst = useFirst, error = error)

} else {
matches <- .pmatchSafe(x, table = table, useFirst = useFirst, error = error)
}

if (length(matches) > nmax) stop('Only ', nmax, ' match(es) can be returned.')

if (length(matches) < length(x)) {
if (length(matches) < length(x) & error) {
if (error) stop('Cannot find a match. Valid options include: ', paste(table, collapse=', '))
}

Expand Down
9 changes: 6 additions & 3 deletions R/roundedSigDigits.r
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#' Number of significant digits in rounded numbers
#'
#' This function "examines" a numeric value (typically with numbers after the decimal place) and estimates either:
#' This function examines a numeric value (typically with numbers after the decimal place) and estimates either:
#' \itemize{
#' \item The number of significant digits of the numerator and denominator of a fraction that would (approximately) result in the given value.
#' \item The number of digits to which an integer may have been rounded, depending on whether the input has values after the decimal place or is an integer. Negative values are treated as positive values so the negative of a number will returns the same value as its positive version. See \emph{Details} for more details. \emph{Obviously, values can appear to be rounded or repeating even when they are not!}
#' \item The number of digits to which an integer may have been rounded, depending on whether the input has values after the decimal place or is an integer. Negative values are treated as positive so the negative of a number will returns the same value as its positive version. See \emph{Details} for more details. \emph{Obviously, values can appear to be rounded or repeating even when they are not!}
#' }
#' @param x Numeric or numeric vector.
#' @param minReps Integer. Number of times a digit or sequence of digits that occur after a decimal place needs to be repeated to assume it represents a repeating series and thus is assumed to arise from using decimal places to represent a fraction. Default is 3. For example, if \code{minReps} is 3 then 0.111 would be assumed to represent a repeating value because 1 occurs three times, so -1 would be returned. However, if \code{minReps} is 4 then the function would assume that if the value had had four digits, the next digit would not have been a 1, so returns -3 because there are three values after the decimal place. When the penultimate digit is >5 and the last digit is equal to the penultimate digit plus 1, then the last digit counts as a repeat of the penultimate digit. So 0.067 is assumed to have two repeating 6s. If \code{minReps} is 0 or 1 then the function will (usually) return the negative of the total number of decimal places in the value.
#' @param minReps Integer. Number of times a digit or sequence of digits that occur after a decimal place needs to be repeated to assume it represents a repeating series and thus is assumed to arise from using decimal places to represent a fraction. Default is 3. For example, if \code{minReps} is 3 then 0.111 would be assumed to represent a repeating value because 1 occurs three times, so -1 would be returned since this decimal can be represented by 1/9 (i.e., division of 1 by a single-digit number). However, if \code{minReps} is 4 then the function would assume that if the value had had four digits, the next digit would not have been a 1, so returns -3 because there are three significant values after the decimal place. When the penultimate digit is >5 and the last digit is equal to the penultimate digit plus 1, then the last digit counts as a repeat of the penultimate digit. So 0.067 is assumed to have two repeating 6s. If \code{minReps} is 0 or 1 then the function will (usually) return the negative of the total number of decimal places in the value.
#'
#' @details For values with at least one non-zero digit after a decimal place with no repeated series of digits detected, the function simply returns the total number of digits (ignoring trailing zeros) times -1. For example:
#' \itemize{
Expand Down Expand Up @@ -83,6 +83,9 @@
#' @export
roundedSigDigits <- compiler::cmpfun(function(x, minReps = 3) {

opts <- options(scipen = 999)
on.exit(options(opts), add = TRUE)

n <- length(x)
out <- rep(NA, n)
numDecDigits <- countDecDigits(x)
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ As of version 1.1.2, `omnibus` is on CRAN! You can install the latest CRAN-stabl
You may need to install the `remotes` package first.

## Data manipulation ##
* `appendLists`: Merge lists, appending elements with the same name.
* `bracket`: Find values that bracket a given number.
* `combineDf`: Combine data frames with different schema.
* `compareFloat`: Compare two values to within floating-point precision.
Expand All @@ -34,7 +35,7 @@ You may need to install the `remotes` package first.
* `insert`: Insert values into a vector.
* `insertCol` and `insertRow`: Insert column(s)/row(s) in a matrix or data frame.
* `maxRuns`: Maximum number of continuous "runs" of values meeting a particular condition.
* `mergeLists`: Merge lists.
* `mergeLists`: Merge lists, with precedence for elements of one list over another if they have the same names.
* `mirror`: Flip an object left-right (or up-down).
* `mmode`: Modal value(s).
* `notIn` and `%notin%`: Opposite of `%in%`.
Expand Down
36 changes: 36 additions & 0 deletions man/appendLists.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions man/mergeLists.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion man/omnibus.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions man/roundedSigDigits.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit dfad6e7

Please sign in to comment.