Search code examples
rlowercaserecode

How to recode all values to lowercase but ignore TRUE and FALSE?


I have data that I want to convert to lowercase and separate with underscores using snakecase::to_any_case(). However, I wish to ignore cells that contain either TRUE/FALSE and keep them as uppercase.

Data

for making a reproducible example

library(dplyr)

df <-
  tibble(animals = c("Peregrine falcon", "Golden eagle", TRUE, "White-throated needletail swift"),
           cars = c("Hennessey Venom GT", FALSE, "Bugatti Chiron Super Sport 300+", "Hennessey Venom F5"),
           airplanes = c("North American X-15", "Lockheed SR-71 Blackbird", FALSE, "Lockheed YF-12")) %>%
  mutate_all(as.character)

##   animals                         cars                            airplanes               
##   <chr>                           <chr>                           <chr>                   
## 1 Peregrine falcon                Hennessey Venom GT              North American X-15     
## 2 Golden eagle                    FALSE                           Lockheed SR-71 Blackbird
## 3 TRUE                            Bugatti Chiron Super Sport 300+ FALSE                   
## 4 White-throated needletail swift Hennessey Venom F5              Lockheed YF-12 

Recoding data

library(snakecase)

df %>% 
  mutate(across(everything(), to_any_case))      # dplyr 1.0.2

##   animals                         cars                           airplanes               
##   <chr>                           <chr>                          <chr>                   
## 1 peregrine_falcon                hennessey_venom_gt             north_american_x_15     
## 2 golden_eagle                    false                          lockheed_sr_71_blackbird
## 3 true                            bugatti_chiron_super_sport_300 false                   
## 4 white_throated_needletail_swift hennessey_venom_f_5            lockheed_yf_12 

But I'm trying to achieve this

  animals                         cars                           airplanes               
  <chr>                           <chr>                          <chr>                   
1 peregrine_falcon                hennessey_venom_gt             north_american_x_15     
2 golden_eagle                    FALSE                          lockheed_sr_71_blackbird
3 TRUE                            bugatti_chiron_super_sport_300 FALSE                   
4 white_throated_needletail_swift hennessey_venom_f_5            lockheed_yf_12   

How can I run mutate(across(everything(), to_any_case)) while ignoring TRUE and FALSE values?


Solution

  • I am not an expert in dplyr syntax, but the following should work:

    library(snakecase)
    
    to_any_no_tf <- function(x) {
        ifelse(!grepl("^(?:TRUE|FALSE)$", x), to_any_case(x), x)
    }
    
    df %>% mutate(across(everything(), to_any_no_tf))
    

    The logic here is to use grepl to check if the input value be the strings TRUE or FALSE. If so, then we do not apply any case logic to them, otherwise we call to_any_case() as you are already doing.