dplyr `case_when()` trouble with NA

Viewed 12051
library(tidyverse)
df <- tibble(ID = c("ABC", "EFG", "HIJ", "KLM", "NOP", "QRS"),
             Date = as.Date(c("2019-01-03", "2019-01-08", 
                              "2019-06-09", "2019-06-11",
                              "2019-08-12", "2019-08-21")))
#> # A tibble: 6 x 2
#>   ID    Date
#>   <chr> <date>        
#> 1 ABC   2019-01-03    
#> 2 EFG   2019-01-08    
#> 3 HIJ   2019-06-09    
#> 4 KLM   2019-06-11    
#> 5 NOP   2019-08-12    
#> 6 QRS   2019-08-21 

Let's start with the data frame above. What I want is shown directly below. The first two line items in the data frame satisfy the conditions in my case_when() statement, and are populated with "fizz" and "buzz". The remainder is populated with NA.

df %>% 
  mutate(col3 = case_when(ID == "ABC" & Date == as.Date("2019-01-03") ~ "fizz",
                          ID == "EFG" & Date == as.Date("2019-01-08") ~ "buzz"))
#> # A tibble: 6 x 3
#>   ID    Date       col3 
#>   <chr> <date>     <chr>
#> 1 ABC   2019-01-03 fizz 
#> 2 EFG   2019-01-08 buzz 
#> 3 HIJ   2019-06-09 NA   
#> 4 KLM   2019-06-11 NA   
#> 5 NOP   2019-08-12 NA   
#> 6 QRS   2019-08-21 NA 

Yet when I try to explicitly tell the case_when() function to populate the remainder of the data frame with NA I get the error shown below? Am I not utilizing TRUE ~ NA in the correct fashion?

Doesn't the TRUE ~ _XYZ_ argument tell the function to populate any condition not satisfied by conditions above with _XYZ_?

df %>% 
  mutate(col3 = case_when(ID == "ABC" & Date == as.Date("2019-01-03") ~ "fizz",
                          ID == "EFG" & Date == as.Date("2019-01-08") ~ "buzz",
                          TRUE ~ NA)
#> Error: unexpected ',' in " 
#> ID == "EFG" & Date == as.Date("2019-01-08") ~ "buzz","
2 Answers

Try the following code - it tells case_when that you are expecting the NA to be a character, like the rest of your column. I think you are also missing a bracket above.

df %>% 
  mutate(col3 = case_when(ID == "ABC" & Date == as.Date("2019-01-03") ~ "fizz",
                          ID == "EFG" & Date == as.Date("2019-01-08") ~ "buzz",
                          TRUE ~ as.character(NA)))

# A tibble: 6 x 3
  ID    Date       col3 
  <chr> <date>     <chr>
1 ABC   2019-01-03 fizz 
2 EFG   2019-01-08 buzz 
3 HIJ   2019-06-09 NA   
4 KLM   2019-06-11 NA   
5 NOP   2019-08-12 NA   
6 QRS   2019-08-21 NA 

In case_when(), NAs need to be of the right class.

class("fizz")
[1] "character"

From the documentation:

All RHS values need to be of the same type. Inconsistent types will throw an error.
This applies also to NA values used in RHS: NA is logical, use
typed values like NA_real_, NA_complex, NA_character_, NA_integer_ as appropriate.

https://www.rdocumentation.org/packages/dplyr/versions/0.7.8/topics/case_when

Here you can use NA_character_, a useful shortcut for as.character(NA):

df %>% 
  mutate(col3 = case_when(ID == "ABC" & Date == as.Date("2019-01-03") ~ "fizz",
                          ID == "EFG" & Date == as.Date("2019-01-08") ~ "buzz",
                          TRUE ~ NA_character_))

As said by the documentation, other NA_types exist NA_real_, NA_complex, NA_integer_ for other class of data.

Related