I am struggling in using rename_with()
with the tidyselector any_of()
if there's no match within the latter.
See this example :
library(tidyvese)
iris |>
rename_with(.cols = any_of(contains("Length")),
.fn = ~ifelse(str_detect(.x, "Petal"),
paste0(.x, "_[petal_var]"),
paste0(.x, "_[sepal_var]")))
What it does is basically check if there's any variable that contains the string "Length"
, and then it applies a function according to whether the variable contains the string "Petal"
:
Yes : then rename with a "_[petal_var]"
suffix
No: then rename with a "_[sepal_var]"
suffix
However, this works as long as there's at least one variable matching the any_of()
call.
Let's consider this example where there's no match :
iris |>
rename_with(.cols = any_of(contains("UNMATCHED_STRING")),
.fn = ~ifelse(str_detect(.x, "Petal"),
paste0(.x, "_[petal_var]"),
paste0(.x, "_[sepal_var]")))
This returns :
Error in `rename_with()`:
! `.fn` must return a character vector, not an empty logical vector.
Run `rlang::last_error()` to see where the error occurred.
I understand the issue : there's nothing to pass to the .fn
argument, since no variable matches the tidyselect .col
step.
Unfortunately I see no workaround using rename_with()
(which is strongly desired here). In my more complex case, I need to pass fairly complex renaming functions to different datasets which may contain or not the value of any_of(contains(...))
.
Any help would be greatly appreciated.
For the discussion of this Issue see: https://github.com/tidyverse/dplyr/issues/6688
The simplest work around is to set the parameter paste0(recycle0 = TRUE)
. So in your case this should work:
iris |>
rename_with(.cols = any_of(contains("UNMATCHED_STRING")),
.fn = ~ifelse(str_detect(.x, "Petal"),
paste0(.x, "_[petal_var]", recycle0 = TRUE),
paste0(.x, "_[sepal_var]", recycle0 = TRUE)))
The dplyr package maintainers have included an example to the rename_with
man page to adress this issue.