Using `any` and `all` as logical tests over multiple elements within `case_when`?

Viewed 44

As you can see from the examples below, column A has multiple elements of different lengths. I'm trying to use case_when within a mutate call to create categorical columns that 'tag' subsets of these multiple elements.

For example, we create a dummy dataset:

df <- tribble(
  ~A, ~B,
  c("a", "b", "c", "1", "2"), "alpha",
  c("b", "c", "d", "1"), "beta",
  c("c", "d", "1", "2", "3"), "gamma"
)

And then to evaluate subset membership I'm using any and all over an %in% call, like so:

result <- df %>%
  mutate(
    test = case_when(all(c("a","1") %in% A) ~ "x",
                     any(c("beta","gamma") %in% B) ~ "y")
  )

Here, I'm expecting result$test to show x, y, y. Instead I'm getting NAs.

Is my approach possible? If not, what's the reason and what's the most efficient alternative strategies I could implement?

2 Answers

I guess you may need rowwise

df %>%
rowwise() %>%
mutate(test = case_when(all(c("a","1") %in% A) ~ "x",
                     any(c("beta","gamma") %in% B) ~ "y"))

which gives

  A         B     test
  <list>    <chr> <chr>
1 <chr [5]> alpha x
2 <chr [4]> beta  y
3 <chr [5]> gamma y

You can use purrr's map2_chr to iterate over the list values of A.

library(dplyr)

df %>%
  mutate(test = purrr::map2_chr(A, B, ~case_when(all(c("a","1") %in% .x) ~ "x",
                                          any(c("beta","gamma") %in% .y) ~ "y")))

#   A         B     test 
#  <list>    <chr> <chr>
#1 <chr [5]> alpha x    
#2 <chr [4]> beta  y    
#3 <chr [5]> gamma y    
Related