I am trying to write a specialized ifelse()
function that I want to pass to dplyr::mutate(across())
. The function should replace NA values in columns specified in across()
with those in similarly-named columns.
For instance in the following made-up data, I want to replace missing x_var1
with y_var1
and missing x_var2
with y_var2
:
x <- tribble(~x_var1, ~x_var2, ~y_var1, ~y_var2,
5, 2, 0, 0,
NA, 10, 8, 0,
3, NA, 0, 5,
NA, NA, 7, 9)
I have tried constructing the following function:
ifelse_spec <- function(var) {
new_var = paste("y_", str_remove(cur_column(), "x_"), sep = "")
# print(new_var) # just to check new_var is correct
ifelse(is.na(var), !!sym(new_var) , var) # how to call new_var?
}
x %>%
mutate(across(c(x_var1, x_var2),
~ ifelse_spec(.)))
but it doesn't seem to work.
However, if I run this one-variable case using ifelse
directly, I get the expected result.
x %>%
mutate(across(c(x_var1),
~ifelse(is.na(.), !!sym("y_var1"), .)))
How can I construct a custom ifelse statement that will allow me to call a data variable?
Edit: I got the following to work for the many-variable case, but still using ifelse
and not a different function.
x %>%
mutate(across(c(x_var1, x_var2),
~ifelse(is.na(.), eval(sym(paste("y_", str_remove(cur_column(), "x_"), sep = ""))), . )))
ifelse()
is evaluated within the function's environment and!!sym(new_var)
(e.g."y_var1"
) isn't defined there. You could try evaluating it in its calling frame, adding a.data
argument toifelse_spec
, or rewriting it as a function factory that returns an expression to be evaluated withinmutate()
, but personally I wouldn't lean so heavily on non-standard evaluation if I didn't absolutely need to. – Joe Roe