For ifelse
statements, its fairly easy to run multiple arguments with both functions and direct data manipulations like so:
#### Load Library ####
library(tidyverse)
#### Run Multiple Ifelse Statements ####
iris %>%
mutate(New.Sepal.Width = ifelse(Sepal.Width > 3.5,
"Large",
ifelse(Sepal.Width < 3,
sqrt(Sepal.Width),
NA)))
However I seem to not understand how to do the same with case_when
in dplyr
. If I run a similar code like this:
iris %>%
mutate(New.Sepal.Width = case_when(
Sepal.Width >= 3.5 ~ "Large",
Sepal.Width <= 3 ~ "sqrt(Sepal.Width)",
Sepal.Width > 3 | Sepal.Width < 3.5 ~ "NA"
))
It prints literally sqrt(Sepal.Width)
rather than the square root. If I specify it as a normal function:
iris %>%
mutate(New.Sepal.Width = case_when(
Sepal.Width >= 3.5 ~ "Large",
Sepal.Width <= 3 ~ sqrt(Sepal.Width), # change here
Sepal.Width > 3 | Sepal.Width < 3.5 ~ "NA"
))
This ends up giving me other issues:
Error in `mutate()`:
! Problem while computing `New.Sepal.Width = case_when(...)`.
Caused by error in `case_when()`:
Run `rlang::last_error()` to see where the error occurred.
Is there a way around this?
CodePudding user response:
If you check ?case_when
, you can see that:
The RHS does not need to be logical, but all RHSs must evaluate to the same type of vector.
So you need your RHS to be character only. You can do so by converting sqrt(Sepal.Width)
to a character vector with as.character
and replace NA
with NA_character_
.
You can do:
iris %>%
mutate(New.Sepal.Width = case_when(
Sepal.Width >= 3.5 ~ "Large",
Sepal.Width <= 3 ~ as.character(sqrt(Sepal.Width)),
Sepal.Width > 3 | Sepal.Width < 3.5 ~ NA_character_
))
Note that in dplyr
's development version, and supposedly from dplyr 1.1
and onwards, case_when
no longer requires NA
to be specified beforehand, so this will work:
iris %>%
mutate(New.Sepal.Width = case_when(
Sepal.Width >= 3.5 ~ "Large",
Sepal.Width <= 3 ~ as.character(sqrt(Sepal.Width)),
Sepal.Width > 3 | Sepal.Width < 3.5 ~ NA
))