Little tidyeval question, I've got this function:
coacross <- function(...) {
coalesce(!!!across(...))
}
And then if I do something like this:
aa = tibble(a1 = c(NA, 1), a2 = c(2, NA), b = 3:4) %>%
mutate(a_full = coacross(starts_with('a')))
Works like a charm. But if I do the same outside a function, I get an error:
aa %>% mutate(c = coalesce(!!!across(starts_with('a'))))
Error in `across()`:
! Must only be used inside data-masking verbs like `mutate()`, `filter()`, and
`group_by()`.
What gives? I'm a bit lost here. Thanks!
You've reached the obscure side of tidy eval programming :-/
The problem is that !!!
is evaluated very early by the first verb that happens to support injection operators:
In your first example, there isn't any injection in the mutate()
call. Instead, !!!
is triggered at the coalesce()
call inside coacross()
, and so the timing is correct.
In your second example, !!!
is triggered at the mutate()
call. Injection is the very first thing that happens, which means that mutate()
hasn't had time yet to set up the data-masking context that across()
needs, and so the timing is too late.
To work around this the overlap between injection contexts must be removed. This is what you did by moving the !!!
in another function. An alternative is to inject a call to coalesce()
but that's rather ugly and very hard to understand:
aa |> mutate(c = !!quote(coalesce(!!!across(starts_with('a')))))
I prefer your coacross()
solution.