Search code examples
rdplyrtidyselect

`dplyr::select()` with tidyselection but not error if column doesn't exist


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?


Solution

  • 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"