Search code examples
rtidyversepurrrrlang

Using rlang and map to recode many variables in R


I am cleaning a data set and need to recode many factor variables. I would like to use rlang and map to create a function to do this. My example dataset and code are below. I think I almost got it, but I just can't seem to figure out the bug, probably because I don't fully grasp rlang.

Working dataset:

df1 <- tribble(
~var1, ~var2, ~var3,
"1",   "1",   "1",
"2",   "2",   "2",
"3",   "3",   "3"
)

Here is how I would recode a single variable (and the result I would like):

df1 <- df1 %>%
  mutate(var1 = fct_recode(var1,
                          "0" = "1",
                          "1" = "2",
                          "2" = "3")) 

Here is my working code:

recode = function(...){
  mutate_quo = quos(...)

  map(mutate_quo, ~{
    df1 <- df1 %>%
      mutate(!!.x = fct_recode(!!.x,
                         "0" = "1",
                         "1" = "2",
                         "2" = "3"))
  })
}

This gives the following error:

Error: unexpected '=' in:
"    df1 <- df1 %>%
  mutate(!!.x ="
>                              "0" = "1",
Error: unexpected ',' in "                             "0" = "1","
>                              "1" = "2",
Error: unexpected ',' in "                             "1" = "2","
>                              "2" = "3"))
Error: unexpected ')' in "                             "2" = "3")"
>   })
Error: unexpected '}' in "  }"
> }
Error: unexpected '}' in "}"

If I remove the !!, the function will compile. However, when I then try to call it using recode("var1"), I get the following error:

Error in mutate_impl(.data, dots) : 
Evaluation error: `f` must be a factor (or character vector).. 

I would like to have the function and then just run recode(var1, var2, var3).


Solution

  • Using the suggesting made by @epi10, this works but doesn't use rlang or map.

    df1 <- df1 %>%
      mutate_at(vars(var1, var2, var3),
            function(x) case_when(x <= 1 ~ 0,
                                  x <= 2 ~ 1,
                                  x <= 3 ~ 2))