Reputation: 8494
I have a function that applies to a dataframe, with the exception of some columns. These columns can be filled using tidyselection.
For example, consider this function:
rename_upper = function(df, except=NULL){
except = names(select(df, {{except}}))
rename_with(df, ~ifelse(.x %in% except, .x, toupper(.x)))
}
rename_upper(iris, except=3:5) %>% names()
#> [1] "SEPAL.LENGTH" "SEPAL.WIDTH" "Petal.Length" "Petal.Width" "Species"
rename_upper(iris, except=starts_with("Pet")) %>% names()
#> [1] "SEPAL.LENGTH" "SEPAL.WIDTH" "Petal.Length" "Petal.Width" "SPECIES"
The output is good, but I don't want it to throw an error if except
contains a column that doesn't exist in df
.
For instance, rename_upper(iris, except=6)
throws an error as location 6 doesn't exist.
Using any_of()
is unfortunately not a solution because it would restrict except
to be a character vector and I couldn't use tidyselection anymore.
Can I have the best of both worlds?
Upvotes: 1
Views: 339
Reputation: 887118
Try
rename_upper <- function(df, except=NULL){
except <- rlang::enexpr(except)
if((!is.numeric(except)) && length(as.list(except))== 1)
{
except <- rlang::as_string(except)
}
nm1 <- setdiff(names(df), names(select(df, any_of({{except}}))))
df %>%
rename_with(~ toupper(.x), all_of(nm1))
}
-testing
> rename_upper(iris, except=6) %>%
+ names
[1] "SEPAL.LENGTH" "SEPAL.WIDTH" "PETAL.LENGTH" "PETAL.WIDTH" "SPECIES"
>
> rename_upper(iris, except=starts_with("Pet")) %>%
+ names
[1] "SEPAL.LENGTH" "SEPAL.WIDTH" "Petal.Length" "Petal.Width" "SPECIES"
> rename_upper(iris, except=3:5) %>% names
[1] "SEPAL.LENGTH" "SEPAL.WIDTH" "Petal.Length" "Petal.Width" "Species"
> rename_upper(iris, except=Sepal.Length) %>%
+ names
[1] "Sepal.Length" "SEPAL.WIDTH" "PETAL.LENGTH" "PETAL.WIDTH" "SPECIES"
Upvotes: 1
Reputation: 19097
Maybe use a try
to see if that's any error when select
ing for the except
column?
Here all columns would be renamed with toupper
if there's an error in select
with a warning message.
library(dplyr)
rename_upper = function(df, except=NULL){
tryerror <- try(select(df, {{except}}), silent = T)
if (class(tryerror) == "try-error") {
warning(paste0("Column specified in the except argument not found in dataframe '", deparse(substitute(df)), "'"))
rename_with(df, .cols = everything(), toupper)
} else {
except = names(tryerror)
rename_with(df, ~ifelse(.x %in% except, .x, toupper(.x)))
}
}
# with error
rename_upper(iris, except=523) %>% names()
[1] "SEPAL.LENGTH" "SEPAL.WIDTH" "PETAL.LENGTH" "PETAL.WIDTH"
[5] "SPECIES"
Warning message:
In rename_upper(iris, except = 523) :
Column specified in the except argument not found in dataframe 'iris'
# run as expected
rename_upper(iris, except=3:5) %>% names()
[1] "SEPAL.LENGTH" "SEPAL.WIDTH" "Petal.Length" "Petal.Width"
[5] "Species"
Upvotes: 2