case_when pattern dynamically generated

Had a similar question to Create patterns list from df values for use in case_when but it seems the topic was closed with an answer covering an alternative rather than showing how to programatically generate the case_when conditions.

If anyone else encounters the needs, here's a way to do it with rlang.

library("tidyverse")

# Table with one column called description.
ds <- tibble::tibble(
  description = c(letters, letters, LETTERS)
)

# We'll use this to dynamically create case_when conditions. What we want is if a or b to recode as fruit, if letters 3:10 then record as cars, etc.
recodeMap <- list(
 fruit = c("a", "b"),
 cars = letters[3:10],
 house = letters[11:15]
)

# Converts list above into a table
codeListUnnest <- function(codes) {
  tidyr::unnest(tibble::tibble(code = names(codes), searchString = codes), cols = c(searchString))
}

recodeWithMap <- function(data, col, recodes) {
  # Parses each row as an expression e.g. `description == "a" ~ "fruit"` 
  caseArgs <- codeListUnnest(recodes) %>% 
    mutate(
      cond = glue::glue('{col} == "{searchString}" ~ "{code}"'),
      cond = rlang::parse_exprs(cond)
    )
  
  # Logging, just to peek at what was created above.
  str(caseArgs$cond)

  # Apply the dynamically generated conditions.
  data %>%
    mutate(
      coded = case_when(!!!caseArgs$cond)
    )
}
recodeWithMap(ds, "description", recodeMap)
3 Likes

Thanks, that's slick. Great pattern for doing a hash.

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.