Recoding all but one variable in R

Viewed 77

I'm trying to recode all but one type of element in a column inside a function. The column name changes depending on the input of the function, and also the element in the column which shouldn't be recoded changes depending on the function input.

the data frame (df in code snippet) looks as follows:

... education ...
... bachelor ...
... master ...
... high school ...
... high school ...
... master ...

but could also look like

... gender ...
... male ...
... female ...
... female ...
... female ...
... male ...

The output that I want is the following respectively:

... education ...
... bachelor ...
... rest ...
... rest ...
... rest ...
... rest ...
... gender ...
... male ...
... rest ...
... rest ...
... rest ...
... male ...

I have tried the following:

select_data <- function(df, col_name, do_not_change){
     df <- df %>%
       dplyr::mutate('{col_name}' = recode(col_name, '{do_not_change}' := {{do_not_change}}, .default = "rest"))

So the calls would look as follows respectively:

# case of education
education_df <- function(df, education, 'bachelor')
# case of gender
gender_df <- function(df, gender, 'male')

However, this doesn't seem to be working. Any help would be greatly appreciated. Thanks a ton in advance!

2 Answers

The function can be modified to

select_data <- function(df, col_name, do_not_change){
     df %>%
       dplyr::mutate({{col_name}} := recode({{col_name}}, 
           {{do_not_change}} := {{do_not_change}}, .default = "rest"))
      
       }

and call as

select_data(df, gender, 'male')  
  gender   education
1   male    bachelor
2   rest      master
3   rest high school
4   male      master 

If we need to pass a string, use ensym which can work with both quoted/unquoted input

select_data <- function(df, col_name, do_not_change){
   col_name <- rlang::ensym(col_name)
     df %>%
       dplyr::mutate({{col_name}} := recode(!! col_name, 
           {{do_not_change}} := {{do_not_change}}, .default = "rest"))
      
       }

-testing

> select_data(df, 'gender', 'male') 
  gender   education
1   male    bachelor
2   rest      master
3   rest high school
4   male      master
> select_data(df, gender, 'male')
  gender   education
1   male    bachelor
2   rest      master
3   rest high school
4   male      master

If we pass both arguments as quoted or unquoted

select_data <- function(df, col_name, do_not_change){
   col_name <- rlang::ensym(col_name)
   do_not_change <- rlang::as_string(rlang::ensym(do_not_change))
     df %>%
       dplyr::mutate({{col_name}} := recode(!! col_name, 
           {{do_not_change}} := {{do_not_change}}, .default = "rest"))
      
       }

-testing

> select_data(df, 'gender', 'male') 
  gender   education
1   male    bachelor
2   rest      master
3   rest high school
4   male      master
> select_data(df, gender, male)
  gender   education
1   male    bachelor
2   rest      master
3   rest high school
4   male      master

data

df <- structure(list(gender = c("male", "female", "female", "male"), 
    education = c("bachelor", "master", "high school", "master"
    )), row.names = c(NA, -4L), class = "data.frame")

Would this work ?

df %>%
  mutate(
    gender = ifelse(gender == "male", "male", "rest"),
    education = ifelse(education == "bachelor", "bachelor", "rest"))
Related