-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rewrite case_when()
using vec_case_when()
#6286
Conversation
With backwards compatible support for the old formula interface
I think the proposal of a devtools::load_all(".")
#> ℹ Loading dplyr
x <- c(1, 2, NA, 4, 5)
y <- c(1, 2, 3, NA, 5)
z <- c(1, 2, 3, 4, NA)
case_when(
x <= 2 & y <= 2, "low",
x <= 4 & y <= 4, "med",
x == 5 & z == 5, "different",
is.na(x) | is.na(y) | is.na(z), "unknown",
.default = "high"
)
#> [1] "low" "low" "unknown" "unknown" "unknown" |
@markfairbanks that example is actually a little tricky because of how x <- c(1, 6)
y <- c(1, NA)
case_when(
x <= 2 & y <= 2, "low",
x <= 4 & y <= 4, "med",
.default = "high",
.missing = "unknown"
)
#> [1] "low" "high"
x <= 2 & y <= 2
#> [1] TRUE FALSE
x <= 4 & y <= 4
#> [1] TRUE FALSE It seems like you'd still have to check for missing values with I still think I think this is more of a case where you have to understand what base R gives you rather than a question of how |
This also comes up when x <- c("a", "b", NA, "e")
# NA turned into FALSE in the condition
vec_case_when(
x %in% c("a", "e", "i", "o", "u"), "vowel",
.default = "consonant",
.missing = "missing"
)
#> [1] "vowel" "consonant" "consonant" "vowel" Maybe the original design where x <- c(1, 2, NA)
# NA propagated, then `TRUE ~` overrides the propagation
dplyr::case_when(
x %% 2 == 0 ~ "odd",
TRUE ~ "even"
)
#> [1] "even" "odd" "even"
# NA propagated and `.default` doesn't handle it
vec_case_when(
x %% 2 == 0, "odd",
.default = "even"
)
#> [1] "even" "odd" NA |
Superseded by #6300 |
Closes #6261
Closes #6206
Closes #5106
Closes #6145
Closes #6225
The intention is to move
vec_case_when()
to vctrs and rewrite in C, but getting the semantics right in R is more important for now.vec_case_when()
will also be used to backif_else()
andcoalesce()
for sure. I think it could also backna_if()
. It could additionally backreplace_when()
if we want to implement that.case_when()
has gained a new interface. Formulas are no longer used, instead you pass pairs ofcondition/value
inputs. There is also an explicit.default
argument now, and new.ptype
and.size
arguments.The formula interface still works for now, I'm optimistic that it is 100% backwards compatible. We don't do anything to actively dissuade people from using the formula interface right now. However, you can't use any of the new arguments with the old interface.
Open question:
Should we have a
.missing
argument incase_when()
andvec_case_when()
? This would:if_else()
is.na(x), "value"
for most casesx
itself (see below)We decided that
.default
should ONLY handle the case where allcondition
s areFALSE
. Meaning it doesn't handle the case where no conditions areTRUE
and at least one of those conditions isNA
- theNA
now gets propagated through. This is generally what people want, see this example:The above was the motivating case for this change. But it is a little more frustrating if the
NA
s occur in the computation of the condition rather than inx
itself. I still think the.default
behavior is right, the problem is that it is hard to explicitly handle theNA
cases now. A.missing
argument would allow us to easily explicitly handle the computedNA
s.