ajg
ajg

Reputation: 59

How to rename a column within my own function using a higher-order function?

Overview

I have columns where the observations are all in caps, such as "NORWALK." However, I wrote a function to transform the observations so they only have capitalized first letters such as "Norwalk."

Code

library(dplyr)
capitalizeColumn <- function(dataSet, c) { # c for column
  dataSet%>%
    mutate(c = tolower({{c}}))%>%
    mutate(c = toTitleCase(c))
}
df3 <- df3 %>%
  capitalizeColumn(ResidenceCity)%>%
  rename_all(recode, c= "ResidenceCity")

However, this code outputs a column named "c" whereas I'd like it to output the name of the original column, which is "ResidenceCity" in this case. Right now I have to use the function rename_all to rename the column later on, but I'd like it to be within my capitalizeColumn function. I've tried using a few different higher-order functions within my function but nothing has worked so far.

Upvotes: 1

Views: 148

Answers (3)

Len Greski
Len Greski

Reputation: 10865

@akrun's answer is a right answer for a dplyr based solution (and I upvoted it), but sometimes things are just easier in Base R than the tidyverse, due to the tidyverse's reliance on non-standard evaluation. Here's a Base R version of the function that handles multiple columns from a data frame.

city <- c("CHICAGO","NEW YORK","LOS ANGELES", "DETROIT")
state <- c("ILLINOIS","NEW YORK","CALIFORNIA","MICHIGAN")
data <- data.frame(city,state,stringsAsFactors = FALSE)
capitalizeColumns <- function(df,vars){
     require(tools)
     for(v in vars) df[[v]] <- toTitleCase(tolower(df[[v]]))
     df
}
capitalizeColumns(data,c("city","state"))

...and the output:

> capitalizeColumns(data,c("city","state"))
         city      state
1     Chicago   Illinois
2    New York   New York
3 Los Angeles California
4     Detroit   Michigan
> 

Upvotes: 3

G. Grothendieck
G. Grothendieck

Reputation: 269965

In dplyr 1.0 we can use mutate/across to apply the function specified in the second argument of across to the column or columns specified in the first.

library(dplyr)
library(tools)

capitalizeColumn <- function(data, c) {
  data %>% 
    mutate(across({{c}}, . %>% tolower %>% toTitleCase))
}


df3 <- data.frame(ResidenceCity = "NORWALK")
capitalizeColumn(df3, ResidenceCity)
##   ResidenceCity
## 1       Norwalk

In earlier versions of dplyr (and also in 1.0 though less preferred) mutate_at could be used:

capitalizeColumn <- function(data, c) {
  data %>% 
    mutate_at(vars({{c}}), . %>% tolower %>% toTitleCase)
}

Upvotes: 0

akrun
akrun

Reputation: 887691

We may need to do the assigment operator (:=) instead of = along with evaluating the 'c' on the 'lhs'

capitalizeColumn <- function(dataSet, c) { 
  dataSet%>%
    mutate(!! enquo(c) := tolower({{c}}) %>% tools::toTitleCase(.))

        }


capitalizeColumn(df1, ResidenceCity) 
# A tibble: 1 x 1
#  ResidenceCity
#  <chr>        
#1 Norwalk      

data

df1 <- tibble( ResidenceCity = "NORWALK")

Upvotes: 2

Related Questions