Home > Net >  How to use functions and multiple arguments within case_when in dplyr?
How to use functions and multiple arguments within case_when in dplyr?

Time:10-17

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
  ))
  • Related