karuno
karuno

Reputation: 411

how to simplify repetitive mutate conditions

I have an example df:

df <- data.frame(
  col1 = c(4,5,6,11),
  col2 = c('b','b','c', 'b')
)

> df
  col1 col2
1    4    b
2    5    b
3    6    c
4   11    b

and I mutate based on these conditions:

df2 <- df %>%
  mutate(col3 = case_when(
    col2 == 'b' & col1 == 4 ~ 10,
    col2 == 'b' & col1 == 5 ~ 15,
    col2 == 'b' & col1 == 11 ~ 20,
    col2 == 'c' & col1 == 6 ~ 7)
  )

> df2
  col1 col2 col3
1    4    b   10
2    5    b   15
3    6    c    7
4   11    b   20

You can see that the first 3 conditions are repetitive in that they require col2 == 'b'. Is there some syntax or another package or more efficient way of combining same/similar conditions so that I don't need to repeat col2 == 'b'? Like a one liner that if col2 == 'b' then do these transformations.

Upvotes: 0

Views: 51

Answers (1)

Ric
Ric

Reputation: 5722

You can write nested case_when

df %>% mutate(col3 = case_when(
  col2=="b" ~ case_when(
    col1 == 4 ~ 10,
    col1 == 5 ~ 15,
    col1 == 11 ~ 20), 
  col2=="c" ~ case_when(
    col1 == 6 ~ 7)))

Another solution colud be using a auxiliary table, this way however will limit the flexibility of case_when and only works for equality matches but i suspect is a lot faster.

library(dplyr)

df <- data.frame(
  col1 = c(4,5,6,11),
  col2 = c('b','b','c', 'b')
)

choices <- data.frame(
  col2 = c(rep("b",3),"c"),
  col1 = c(4,5,11,6),
  col3 = c(10,15,20,7)
)

df %>% left_join(choices, by = c("col1"="col1", "col2"="col2"))
#>   col1 col2 col3
#> 1    4    b   10
#> 2    5    b   15
#> 3    6    c    7
#> 4   11    b   20

Be sure to capture the default unmatched cases.

Upvotes: 2

Related Questions