Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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?

>Solution :

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
  ))
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading