Taren Shaw
Taren Shaw

Reputation: 109

tidy eval map over column names

I have made my own function as follows:

    emp_term_var <- function(data, colName, year = "2015") {
  
  # Terminations by year and variable in df
  colName <- enquo(colName) 
  term_test <- data %>%
    filter(year(DateofTermination) == year) %>%
    group_by(UQ(colName)) %>%
    count(UQ(colName)) %>%
    clean_names()
  return(term_test)
  
}

I have a df with multiple columns such as Department, State, Position etc. WHen I want to use the function I have written I put the name of the column without quotations as follows:

emp_term_var(data = df, colName = Department, year = "2015")

Which returns:

# A tibble: 5 x 2
# Groups:   department [5]
  department               n
  <chr>                <int>
1 Admin Offices            1
2 IT/IS                    4
3 Production              15
4 Sales                    1
5 Software Engineering     2
> 

How can I map over mulitple columns? if I try

columns <- c(Department, State)

R does not lelt me as it identifies these as objects and not column names. How can I make R know that these are column names to be stored in the object columns so I can pass it to map in this form:

map(colnames, ~ emp_term_var(df, colName = .x, year = "2015"))

Upvotes: 2

Views: 407

Answers (2)

Lionel Henry
Lionel Henry

Reputation: 6803

Another solution is to keep your function as is but change the way you call it inside map():

columns <- c("Department", "State")

map(colnames, ~ emp_term_var(df, colName = .data[[.x]], year = "2015"))

Note how we pass colName = .data[[.x]] instead of colName = .x.

You can also do this in other contexts like a for loop:

for (col in columns) {
  print(
    emp_term_var(df, colName = .data[[col]], year = "2015")
  )
}

Upvotes: 6

akrun
akrun

Reputation: 886938

Instead of using enquo change it to either .data or convert to symbols with ensym and evaluate (!!)

emp_term_var <- function(data, colName, year = "2015") {
  
  # Terminations by year and variable in df
  colName <- ensym(colName) 
  term_test <- data %>%
    filter(year(DateofTermination) == year) %>%
    #group_by(!!colName)) %>%
    count(!!(colName)) %>%
    clean_names()
  return(term_test)
  
}

NOTE: count can take the column without any grouping as well

The advantage with ensym route is that it can both quoted and unquoted input i.e. it takes the string as column names and without the quotes

nm1 <- c("Department", "State")
purrr::map(nm1, ~ emp_term_var(df, colName = !!.x, year = "2015"))

or if we want to use

emp_term_var(data = df, colName = Department, year = "2015")

Or can take

emp_term_var(data = df, colName = "Department", year = "2015")

Upvotes: 2

Related Questions