Using map on a conditional statement inside a mutate command

Advertisements

I have a data frame containing numbers that I would like to bin according to their absolute value.

library(tidyverse)
dat <- data.frame(val = seq(-10, 10)) 

The following command accomplishes what I would like to do, but the values are hardcoded which I need to avoid:

dat %>% 
  mutate(grp = case_when(abs(val) <= 5 ~ "Grp 1",
                         abs(val) <= 7 ~ "Grp 2",
                         TRUE ~ "Grp 3"))

How can I accomplish the same transformation, but instead using a named vector as the input:

grps <- c("Grp 1" = 5, "Grp 2" = 7)

So that I can add/remove groups as needed, for example, adding in "Grp 3" = 9?

>Solution :

Instead of using map or something that works one-by-one, we can do it vectorized with cut:

grps <- c("Grp 1" = 5, "Grp 2" = 7)
dat %>%
  mutate(
    grp = cut(abs(val), c(-Inf, grps, Inf), labels = c(names(grps), "Grp 3"))
  )
#    val   grp
# 1  -10 Grp 3
# 2   -9 Grp 3
# 3   -8 Grp 3
# 4   -7 Grp 2
# 5   -6 Grp 2
# 6   -5 Grp 1
# 7   -4 Grp 1
# 8   -3 Grp 1
# 9   -2 Grp 1
# 10  -1 Grp 1
# 11   0 Grp 1
# 12   1 Grp 1
# 13   2 Grp 1
# 14   3 Grp 1
# 15   4 Grp 1
# 16   5 Grp 1
# 17   6 Grp 2
# 18   7 Grp 2
# 19   8 Grp 3
# 20   9 Grp 3
# 21  10 Grp 3

Note that grp is a factor; if you want it to be character, just wrap it in as.character.

Leave a ReplyCancel reply