Type: | Package |
Title: | Pipe-Friendly Vector Replacement with Case Statements |
Version: | 0.3.2 |
Description: | Offers a pipe-friendly alternative to the 'dplyr' functions case_when() and if_else(), as well as a number of user-friendly simplifications for common use cases. These functions accept a vector as an optional first argument, allowing conditional statements to be built using the 'magrittr' dot operator. The functions also coerce all outputs to the same type, meaning you no longer have to worry about using specific typed variants of NA or explicitly declaring integer outputs, and evaluate outputs somewhat lazily, so you don't waste time on long operations that won't be used. |
License: | MIT + file LICENSE |
URL: | https://pkg.rossellhayes.com/incase/, https://github.com/rossellhayes/incase |
BugReports: | https://github.com/rossellhayes/incase/issues |
Imports: | backports, cli, magrittr, plu, rlang |
Suggests: | dplyr, testthat (≥ 3.0.0), tibble |
Config/testthat/edition: | 3 |
Encoding: | UTF-8 |
RoxygenNote: | 7.2.3 |
NeedsCompilation: | no |
Packaged: | 2023-08-21 04:54:38 UTC; alex |
Author: | Alexander Rossell Hayes
|
Maintainer: | Alexander Rossell Hayes <alexander@rossellhayes.com> |
Repository: | CRAN |
Date/Publication: | 2023-08-21 05:32:33 UTC |
incase: Pipe-Friendly Vector Replacement with Case Statements
Description
Offers a pipe-friendly alternative to dplyr::case_when()
and
dplyr::if_else()
.
These functions accept a vector as an optional first argument, allowing
conditional statements to be built using the magrittr
dot operator.
The functions also coerce all possible outputs to the same type, meaning you
no longer have to worry about using specific typed variants of NA
or
explicitly declaring integer outputs.
Copyright
incase includes code from dplyr, which is licensed under the MIT License:
Copyright (c) 2013-2019 RStudio and others.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Author(s)
Maintainer: Alexander Rossell Hayes alexander@rossellhayes.com (ORCID) [copyright holder]
Other contributors:
Patrice Kiener fattailsr@inmodelia.com (ORCID) (Contributed example for fn_case()) [contributor]
See Also
Useful links:
Report bugs at https://github.com/rossellhayes/incase/issues
Pipe operator
Description
See magrittr::%>%
for details.
Usage
lhs %>% rhs
Case statements applying a function to all inputs
Description
Case statements applying a function to all inputs
Usage
fn_case(x, fn, ..., preserve = FALSE, default = NA)
Arguments
x |
A vector |
fn |
A function to apply to the left-hand side of each formula in Either a quoted or unquoted function name, an anonymous The function should take two inputs, the first being |
... |
<
|
preserve |
If |
default |
If |
Value
A vector of length 1 or n, matching the length of the logical input or output vectors. Inconsistent lengths will generate an error.
See Also
fn_case_fct()
to return a factor and
fn_case_list()
to return a list
fn_switch_case()
, which applies a function to each formula's LHS,
but not x
switch_case()
, a simpler alternative for exact matching
grep_case()
, a simpler alternative for regex pattern matching
in_case()
, a pipeable alternative to dplyr::case_when()
Examples
# Replicate switch_case()
parties <- sample(c("d", "r", "i", "g", "l"), 20, replace = TRUE)
fn_case(
parties,
fn = `%in%`,
"d" ~ "Democrat",
"r" ~ "Republican",
"i" ~ "Independent",
"g" ~ "Green",
"l" ~ "Libertarian"
)
# Replicate grep_case()
countries <- c(
"France", "Ostdeutschland", "Westdeutschland", "Nederland",
"Belgie (Vlaanderen)", "Belgique (Wallonie)", "Luxembourg", "Italia"
)
fn_case(
countries,
fn = function(x, pattern, ...) {grepl(pattern, x, ...)},
"Deutschland" ~ "Germany",
"Belgi(qu)?e" ~ "Belgium",
"Nederland" ~ "Netherlands",
"Italia" ~ "Italy",
preserve = TRUE,
ignore.case = TRUE
)
fn_case(
countries,
fn = ~ grepl(.y, .x),
"Deutschland" ~ "Germany",
"Belgi(qu)?e" ~ "Belgium",
"Nederland" ~ "Netherlands",
"Italia" ~ "Italy",
preserve = TRUE,
ignore.case = TRUE
)
# Recode values in a range
time <- runif(10, 1, 12)
hours <- time %/% 1
minutes <- time %% 1 * 60
hours <- hours %>%
if_case(minutes > 32.5, (. + 1) %% 12, .) %>%
switch_case(0 ~ 12, preserve = TRUE)
minutes %>%
fn_case(
fn = ~ abs(.x - .y) <= 2.5,
0 ~ "o'clock",
60 ~ "o'clock",
30 ~ "half past",
15 ~ "quarter past",
45 ~ "quarter to",
5 ~ "five past",
10 ~ "ten past",
20 ~ "twenty past",
25 ~ "twenty-five past",
55 ~ "five to",
50 ~ "ten to",
40 ~ "twenty to",
35 ~ "twenty-five to"
) %>%
switch_case(
"o'clock" ~ paste(hours, .),
default = paste(., hours)
)
# Replicate vctrs::vec_ptype_abbr() (used for tibble column labels)
# Based on a contribution by Patrice Kiener
in_herits <- function(x) {
fn_case(
x,
fn = inherits,
"factor" ~ "fct",
"character" ~ "chr",
"numeric" ~ "dbl",
"integer" ~ "int",
"logical" ~ "lgl",
"complex" ~ "cpl",
"raw" ~ "raw",
"matrix" ~ "mat",
"array" ~ "arr",
"data.frame" ~ "df",
"list" ~ "lst",
"function" ~ "fn",
default = class(x)[[1]]
)
}
in_herits(1:3)
in_herits(letters[1:3])
in_herits(fn_case)
Switch-style recoding of values with string pattern matching
Description
Switch-style recoding of values with string pattern matching
Usage
grep_case(x, ..., preserve = FALSE, default = NA)
Arguments
x |
A vector |
... |
<
|
preserve |
If |
default |
If |
Value
A vector of the same length as x
.
See Also
grep_case_fct()
to return a factor and
grep_case_list()
to return a list
fn_case()
, to apply a function other than grepl()
to each case
switch_case()
to recode values with exact matching
in_case()
, a pipeable alternative to dplyr::case_when()
switch()
and grepl()
, which inspired this function
Examples
words <- c("caterpillar", "dogwood", "catastrophe", "dogma")
grep_case(
words,
"cat" ~ "feline",
"dog" ~ "canine"
)
caps_words <- c("caterpillar", "dogwood", "Catastrophe", "DOGMA")
grep_case(
caps_words,
"cat" ~ "feline",
"dog" ~ "canine",
ignore.case = TRUE
)
countries <- c(
"France", "Ostdeutschland", "Westdeutschland", "Nederland",
"Belgie (Vlaanderen)", "Belgique (Wallonie)", "Luxembourg", "Italia"
)
grep_case(
countries,
"Deutschland" ~ "Germany",
"Belgi(qu)?e" ~ "Belgium",
"Nederland" ~ "Netherlands",
"Italia" ~ "Italy",
preserve = TRUE,
ignore.case = TRUE
)
Pipe-friendly vectorized if
Description
Compared to dplyr::if_else()
, this function is easier to use with a pipe.
A vector piped into this function will be quietly ignored.
This allows magrittr dots to be used in arguments without requiring
workarounds like wrapping the function in braces.
Usage
if_case(condition, true, false, missing = NA, ...)
Arguments
condition |
Logical vector |
true , false , missing |
Values to use for |
... |
Values passed to |
Details
This function is also less strict than dplyr::if_else()
.
If true
, false
, and missing
are different types, they are silently
coerced to a common type.
Value
Where condition
is TRUE
, the matching value from true
;
where it's FALSE
, the matching value from false
;
and where it's NA
, the matching value from missing
.
See Also
in_case()
, a pipeable alternative to dplyr::case_when()
switch_case()
, a reimplementation of switch()
dplyr::if_else()
, from which this function is derived
Examples
x <- c(1, 2, 5, NA)
# if_case() produces the same output as dplyr::if_else()
if_case(x > 3, "high", "low", "missing")
dplyr::if_else(x > 3, "high", "low", "missing")
# if_case() does not throw an error if arguments are not of the same type
if_case(x > 3, "high", "low", NA)
try(dplyr::if_else(x > 3, "high", "low", NA))
# if_case() can accept a piped input without an error or requiring braces
x %>% if_case(. > 3, "high", "low", "missing")
try(x %>% dplyr::if_else(. > 3, "high", "low", "missing"))
x %>% {dplyr::if_else(. > 3, "high", "low", "missing")}
# You can also pipe a conditional test like dplyr::if_else()
{x > 3} %>% if_case("high", "low", "missing")
{x > 3} %>% dplyr::if_else("high", "low", "missing")
A pipe-friendly general vectorized if
Description
This function allows you to vectorize multiple if_else() statements.
If no cases match, NA is returned.
This function derived from dplyr::case_when()
.
Unlike dplyr::case_when()
, in_case()
supports piping elegantly and
attempts to handle inconsistent types (see examples).
Usage
in_case(..., preserve = FALSE, default = NA)
Arguments
... |
< The LHS must evaluate to a logical vector. Both LHS and RHS may have the same length of either 1 or
|
preserve |
If |
default |
If |
Value
A vector of length 1 or n, matching the length of the logical input or output vectors. Inconsistent lengths will generate an error.
See Also
in_case_fct()
to return a factor and
in_case_list()
to return a list
switch_case()
a simpler alternative for when each case involves
==
or %in%
fn_case()
, a simpler alternative for when each case uses the
same function
if_case()
, a pipeable alternative to dplyr::if_else()
dplyr::case_when()
, from which this function is derived
Examples
# Non-piped statements are handled the same as dplyr::case_when()
x <- 1:30
in_case(
x %% 15 == 0 ~ "fizz buzz",
x %% 3 == 0 ~ "fizz",
x %% 5 == 0 ~ "buzz",
TRUE ~ x
)
# A vector can be directly piped into in_case() without error
1:30 %>%
in_case(
. %% 15 == 0 ~ "fizz buzz",
. %% 3 == 0 ~ "fizz",
. %% 5 == 0 ~ "buzz",
TRUE ~ .
)
# in_case() silently converts types
1:30 %>%
in_case(
. %% 15 == 0 ~ 35,
. %% 3 == 0 ~ 5,
. %% 5 == 0 ~ 7,
TRUE ~ NA
)
x <- 1:30
try(
dplyr::case_when(
x %% 15 == 0 ~ 35,
x %% 3 == 0 ~ 5,
x %% 5 == 0 ~ 7,
TRUE ~ NA
)
)
# default and preserve make it easier to handle unmatched values
1:30 %>%
in_case(
. %% 15 == 0 ~ "fizz buzz",
. %% 3 == 0 ~ "fizz",
. %% 5 == 0 ~ "buzz",
default = "pass"
)
1:30 %>%
in_case(
. %% 15 == 0 ~ "fizz buzz",
. %% 3 == 0 ~ "fizz",
. %% 5 == 0 ~ "buzz",
preserve = TRUE
)
Case statements returning a factor
Description
These functions are equivalent to in_case()
, switch_case()
,
grep_case()
, fn_case()
, and fn_switch_case()
but return
factors with their levels determined by the order of their
case statements.
Usage
in_case_fct(..., preserve = FALSE, default = NA, ordered = FALSE)
switch_case_fct(x, ..., preserve = FALSE, default = NA, ordered = FALSE)
grep_case_fct(x, ..., preserve = FALSE, default = NA, ordered = FALSE)
fn_case_fct(x, fn, ..., preserve = FALSE, default = NA, ordered = FALSE)
fn_switch_case_fct(x, fn, ..., preserve = FALSE, default = NA, ordered = FALSE)
Arguments
... |
<
|
preserve |
If |
default |
If |
ordered |
A logical.
If |
x |
A vector |
fn |
A function to apply to the left-hand side of each formula in Either a quoted or unquoted function name, an anonymous The function should take two inputs, the first being |
Value
A factor vector of length 1 or n, matching the length of the logical
input or output vectors.
Levels are determined by the order of inputs to ...
.
Inconsistent lengths will generate an error.
See Also
in_case()
, switch_case()
, grep_case()
, fn_case()
, and
fn_case_fct()
on which these functions are based.
Examples
1:10 %>%
in_case_fct(
. %% 2 == 0 ~ "even",
. %% 2 == 1 ~ "odd"
)
switch_case_fct(
c("a", "b", "c"),
"c" ~ "cantaloupe",
"b" ~ "banana",
"a" ~ "apple"
)
switch_case_fct(
c("a", "b", "c", "d"),
"c" ~ "cantaloupe",
"b" ~ "banana",
"a" ~ "apple"
)
switch_case_fct(
c("a", "b", "c", "d"),
"c" ~ "cantaloupe",
"b" ~ "banana",
"a" ~ "apple",
preserve = TRUE
)
grep_case_fct(
c("caterpillar", "dogwood", "catastrophe", "dogma"),
"cat" ~ "feline",
"dog" ~ "canine"
)
fn_case_fct(
c("a", "b", "c"),
`%in%`,
"c" ~ "cantaloupe",
"b" ~ "banana",
"a" ~ "apple"
)
Case statements returning a list
Description
These functions are equivalent to in_case()
, switch_case()
,
grep_case()
, fn_case()
, and fn_switch_case()
but return
lists.
Usage
in_case_list(..., preserve = FALSE, default = NA)
switch_case_list(x, ..., preserve = FALSE, default = NA)
grep_case_list(x, ..., preserve = FALSE, default = NA)
fn_case_list(x, fn, ..., preserve = FALSE, default = NA)
fn_switch_case_list(x, fn, ..., preserve = FALSE, default = NA)
Arguments
... |
<
|
preserve |
If |
default |
If |
x |
A vector |
fn |
A function to apply to the left-hand side of each formula in Either a quoted or unquoted function name, an anonymous The function should take two inputs, the first being |
Details
This can be useful when returning a non-atomic value and/or when you want to create a list column inside a tibble.
Value
A list of length 1 or n, matching the length of the logical input vector.
See Also
in_case()
, switch_case()
, grep_case()
, fn_case()
, and
fn_case_fct()
on which these functions are based.
Examples
1:3 %>%
in_case_list(
. < 2 ~ mtcars,
default = letters
)
Switch-style recoding of values
Description
Switch-style recoding of values
Usage
switch_case(x, ..., preserve = FALSE, default = NA)
fn_switch_case(x, fn, ..., preserve = FALSE, default = NA)
Arguments
x |
A vector |
... |
<
|
preserve |
If |
default |
If |
fn |
A function to apply to the left-hand side of each formula in |
Value
A vector of the same length as x
.
See Also
switch_case_fct()
and fn_switch_case_fct()
to return a factor
and switch_case_list()
and fn_switch_case_list()
to return a list
grep_case()
to recode values with string pattern matching
fn_case()
, which applies a function to both x
and each formula's LHS
in_case()
, a pipeable alternative to dplyr::case_when()
switch()
and %in%
, which inspired this function
Examples
parties <- sample(c("d", "r", "i", "g", "l"), 20, replace = TRUE)
switch_case(
parties,
"d" ~ "Democrat",
"r" ~ "Republican",
"i" ~ "Independent",
"g" ~ "Green",
"l" ~ "Libertarian"
)
parties %>%
switch_case(
"d" ~ "Democrat",
"r" ~ "Republican",
"i" ~ "Independent",
"g" ~ "Green",
"l" ~ "Libertarian"
)
parties %>%
switch_case(
"d" ~ "Democrat",
"r" ~ "Republican",
c("i", "g", "l") ~ "Other"
)
parties %>%
switch_case(
"d" ~ "Democrat",
"r" ~ "Republican",
default = "Other"
)
parties %>%
switch_case(
"d" ~ "Democrat",
"r" ~ "Republican",
preserve = FALSE
)
parties %>%
switch_case(
"d" ~ "Democrat",
"r" ~ "Republican",
preserve = TRUE
)
data <- c(1, 4, 8, 12, 999, 6, 2, 888, 4, 6, 777)
fn_switch_case(
data,
function(x) paste(rep(x, 3), collapse = ""),
7 ~ "Not asked",
8 ~ "Refused",
9 ~ "Missing",
preserve = TRUE
)