|
| 1 | +#' Vectorized if-else |
| 2 | +#' |
| 3 | +#' @description |
| 4 | +#' `vec_if_else()` is a vectorized [if-else][if]. Compared to the base R |
| 5 | +#' equivalent, [ifelse()], this function allows you to handle missing values in |
| 6 | +#' the `condition` with `missing` and always takes `true`, `false`, and |
| 7 | +#' `missing` into account when determining what the output type should be. |
| 8 | +#' |
| 9 | +#' @inheritParams rlang::args_dots_empty |
| 10 | +#' @inheritParams rlang::args_error_context |
| 11 | +#' |
| 12 | +#' @param condition A logical vector. |
| 13 | +#' |
| 14 | +#' @param true,false Vectors to use for `TRUE` and `FALSE` values of |
| 15 | +#' `condition`. |
| 16 | +#' |
| 17 | +#' Both `true` and `false` will be [recycled][theory-faq-recycling] |
| 18 | +#' to the size of `condition`. |
| 19 | +#' |
| 20 | +#' `true`, `false`, and `missing` (if used) will be cast to their common type. |
| 21 | +#' |
| 22 | +#' @param missing If not `NULL`, will be used as the value for `NA` values of |
| 23 | +#' `condition`. Follows the same size and type rules as `true` and `false`. |
| 24 | +#' |
| 25 | +#' @param ptype An optional prototype declaring the desired output type. If |
| 26 | +#' supplied, this overrides the common type of `true`, `false`, and `missing`. |
| 27 | +#' |
| 28 | +#' @param condition_arg,true_arg,false_arg,missing_arg Argument names used in |
| 29 | +#' error messages. |
| 30 | +#' |
| 31 | +#' @returns |
| 32 | +#' A vector with the same size as `condition` and the same type as the common |
| 33 | +#' type of `true`, `false`, and `missing`. |
| 34 | +#' |
| 35 | +#' Where `condition` is `TRUE`, the matching values from `true`, where it is |
| 36 | +#' `FALSE`, the matching values from `false`, and where it is `NA`, the matching |
| 37 | +#' values from `missing`, if provided, otherwise a missing value will be used. |
| 38 | +#' |
| 39 | +#' @export |
| 40 | +#' @examples |
| 41 | +#' x <- c(-5:5, NA) |
| 42 | +#' vec_if_else(x < 0, NA, x) |
| 43 | +#' |
| 44 | +#' # Explicitly handle `NA` values in the `condition` with `missing` |
| 45 | +#' vec_if_else(x < 0, "negative", "positive", missing = "missing") |
| 46 | +#' |
| 47 | +#' # Unlike `ifelse()`, `vec_if_else()` preserves types |
| 48 | +#' x <- factor(sample(letters[1:5], 10, replace = TRUE)) |
| 49 | +#' ifelse(x %in% c("a", "b", "c"), x, NA) |
| 50 | +#' vec_if_else(x %in% c("a", "b", "c"), x, NA) |
| 51 | +#' |
| 52 | +#' # `vec_if_else()` also works with data frames |
| 53 | +#' condition <- c(TRUE, FALSE, NA, TRUE) |
| 54 | +#' true <- data_frame(x = 1:4, y = 5:8) |
| 55 | +#' false <- data_frame(x = 9:12, y = 13:16) |
| 56 | +#' vec_if_else(condition, true, false) |
| 57 | +vec_if_else <- function( |
| 58 | + condition, |
| 59 | + true, |
| 60 | + false, |
| 61 | + ..., |
| 62 | + missing = NULL, |
| 63 | + ptype = NULL, |
| 64 | + condition_arg = "condition", |
| 65 | + true_arg = "true", |
| 66 | + false_arg = "false", |
| 67 | + missing_arg = "missing", |
| 68 | + error_call = current_env() |
| 69 | +) { |
| 70 | + check_dots_empty0(...) |
| 71 | + .Call( |
| 72 | + ffi_vec_if_else, |
| 73 | + condition, |
| 74 | + true, |
| 75 | + false, |
| 76 | + missing, |
| 77 | + ptype, |
| 78 | + environment() |
| 79 | + ) |
| 80 | +} |
0 commit comments