When I use case_when as below, I end up with an unwanted doubling of outputs that were intended to be of length 1 - presumably because case_when matches the length of all possible output vectors.
a <- 1
b <- 2
decision <- case_when(
a == b ~ c("A", "B"),
a > b ~ "A",
TRUE ~ "B")
result <- decision %>% str_c(" ") %>% paste(collapse = " ")
The result in this scenario is "B B ", when I just want "B ".
When a=b, I get "A B ", which is what I want in that scenario.
Is there any way to stop this behaviour, or an alternative function?
Please note that the above is just the simplest parallel I could write. I am using case_when as part of a custom function to define rules applied to numerous input variables to generate a result call. I had been using multiple if_else statements chained together, but that has significant readability/editing issues and I had been excited to discover case_when and use it instead.
CodePudding user response:
case_when/ifelse/if_else
all requires arguments to have equal length. Here, the value returned in some cases have length 2 and some have length 1. It wouldn't work as mentioned in the ?case_when
Both LHS and RHS may have the same length of either 1 or n. The value of n must be consistent across all cases. The case of n == 0 is treated as a variant of n != 1.
Use if/else
decision <- if(a == b) c('A', 'B') else if(a > b) 'A' else 'B'
-testing
library(stringr)
decision %>%
str_c(" ") %>%
str_c(collapse = " ")
[1] "B "
If we want to still use case_when
, wrap it with list
so that it returns a length of 1 for all cases and then extract the list
element with [[
case_when(
a == b ~ list(c("A", "B")),
a > b ~ list("A"),
TRUE ~ list("B"))[[1]]
[1] "B"
CodePudding user response:
If you want to use case_when
you could also use some regex
:
a <- 1
b <- 2
decision <- case_when(
a == b ~ "A B",
a > b ~ "A",
TRUE ~ "B")
stringr::str_replace_all(decision, "([A-B])", "\\1\\ ")