R dplyr case_when error trying to return expression

Viewed 585

I'm trying to use case_when to create groupings in a dataframe instead of multiple if_else statements in a dplyr chain.

Unfortunately I've run into this error when trying to return an expression (to then use them to display nice maths expressions in a ggplot)

Error: Problem with `mutate()` input `output`.
x Input `output` must be a vector, not an expression vector.
i Input `output` is `case_when(...)`.
Run `rlang::last_error()` to see where the error occurred.

Here is a MWE:

library(dplyr)

fizzbuzz <- data.frame(input = seq(0, 50))
fizzbuzz %>% mutate(
  output = case_when(
    input %% 35 == 0 ~ expression(f*b[found]),
    input %% 5 == 0 ~ expression(f),
    input %% 7 == 0 ~ expression(b),
    TRUE ~ expression(0)
  )
)
# %>% other dplyr operations then ggplot using `output` as a facet
# Fails with error shown above

input = seq(0, 50)
output <- case_when(
  input %% 35 == 0 ~ expression(f*b[found]),
  input %% 5 == 0 ~ expression(f),
  input %% 7 == 0 ~ expression(b),
  TRUE ~ expression(0)
)
# works ok, but is an expression not a vector:
# > output
# expression(f * b[found], 0, 0, 0, 0, f, 0, b, 0, 0, f, 0, 0, 
#     0, b, f, 0, 0, 0, 0, f, b, 0, 0, 0, f, 0, 0, b, 0, f, 0, 
#     0, 0, 0, f * b[found], 0, 0, 0, 0, f, 0, b, 0, 0, f, 0, 0, 
#     0, b, f)

I think there should be a way to to either convert the expression to a vector? I'm not sure why dplyr doesn't automatically convert it into a vector and couldn't find anything online. TIA!

1 Answers

As the error says

Input `output` must be a vector, not an expression vector.

You need to convert the expression vector to a list by as.list().

library(dplyr)

fizzbuzz <- data.frame(input = seq(0, 50))
fizzbuzz %>% mutate(
  output = as.list(case_when(
    input %% 35 == 0 ~ expression(f*b[found]),
    input %% 5 == 0 ~ expression(f),
    input %% 7 == 0 ~ expression(b),
    TRUE ~ expression(0)
  ))
)

#    input       output
# 1      0 f * b[found]
# 2      1            0
# 3      2            0
# 4      3            0
# 5      4            0
# 6      5            f
# 7      6            0
# 8      7            b
Related