Skip to content

Instantly share code, notes, and snippets.

@alandipert
Last active June 12, 2017 17:39
Show Gist options
  • Save alandipert/6ca9f895fa0a4527deaa78292a0488c7 to your computer and use it in GitHub Desktop.
Save alandipert/6ca9f895fa0a4527deaa78292a0488c7 to your computer and use it in GitHub Desktop.
#' Chained Conditional Element Selection
#'
#' \code{cond} takes even number of arguments representing a series of
#' \code{test}/\code{value} pairs, and returns a value with the same shape as
#' every \code{test}. The returned element is filled with the elements selected
#' from every \code{value} depending on whether its corresponding \code{test} is
#' \code{TRUE} or \code{FALSE}.
#'
#' @param ... An even number of \code{test}/\code{value} pairs. Every \code{test}
#' is coerced to logical mode. \code{test} arguments should be the same shape.
#' @param default Atomic value to use if no \code{test} was satisfied, or \code{NA} if not specified.
#' @examples
#' chars <- letters[1:5]
#' cond(chars %in% c("a", "c"),
#' as.character(1:5),
#' chars == "e",
#' "X",
#' default = chars)
#' @seealso \code{\link{ifelse}}
cond <- function(..., default = NA, env = parent.frame()) {
args <- eval(substitute(alist(...)))
if (length(args) == 0) {
return(default)
} else if (length(args) %% 2 != 0) {
stop("cond requires an even number of arguments")
}
test <- as.logical(eval(args[[1]], envir = env))
ans <- test
ok <- !(nas <- is.na(test))
if (any(test[ok]))
ans[test & ok] <- rep(eval(args[[2]], envir = env),
length.out = length(ans))[test & ok]
if (any(!test[ok]))
ans[!test & ok] <- do.call(cond, c(args[-1:-2], list(default = default, env = env)))[!test & ok]
ans[nas] <- NA
ans
}
@alandipert
Copy link
Author

Note: a control-flow cond can be found here: https://gist.github.com/DASpringate/8595464

@kaz-yos
Copy link

kaz-yos commented Jun 12, 2017

Cool stuff. I used it in my work. Also I just learned that dplyr has the same (?) functionality with dplyr::case_when() https://www.rdocumentation.org/packages/dplyr/versions/0.5.0/topics/case_when

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment