Moses
Moses

Reputation: 1484

Is there a way to use mutate inside of ones own function?

Am trying to use mutate function inside my own created function to in order to deal with DRY principle. Am not sure if it would be possible. Whenever I run the function collapsevars I get the correct answer but the mutate function does not pick the variable name specified in the collapsevars function. Any leads? The sample code is as below:

library(dplyr)

set.seed(2021)

avars <- c("a1", "a2") # Variables to collapse to a single variable
bvars <- c("b1", "b2") # Variables to collapse to another variable

mydata <- tibble(
  a1 = factor(round(runif(20, 1, 3)),
              labels = c("Yes", "No", "N/A")),
  a2 = factor(round(runif(20, 1, 3)),
              labels = c("Yes", "No", "N/A")),
  b1 = factor(round(runif(20, 1, 3)),
              labels = c("Yes", "No", "N/A")),
  b2 = factor(round(runif(20, 1, 3)),
              labels = c("Yes", "No", "N/A")),

  c1 = round(rnorm(20, 10, 2)))
mydata

mydata <- mydata %>%
  mutate(afin = ifelse(rowSums(
    select(., all_of(avars)) == "Yes") > 0,
                       "Yes", "No"),
         bfin = ifelse(rowSums(
           select(., all_of(bvars)) == "Yes") > 0,
                       "Yes", "No"))

collapsevars <- function(var, varcollapse){
  mydata <- mydata %>%
    mutate(var = ifelse(rowSums(
      select(., all_of(varcollapse)) == "Yes") > 0,
                         "Yes", "No"))

}

collapsevars(afin, avars)

Upvotes: 3

Views: 166

Answers (3)

akrun
akrun

Reputation: 887831

Using case_when

library(dplyr)
collapsevars <- function(var, varcollapse){
 mydata %>%
    mutate({{var}} := case_when(rowSums(
          select(., all_of(varcollapse)) == "Yes") > 0 ~ 
      "Yes", TRUE ~ "No"))
 
}
collapsevars(afin, avars)

Upvotes: 2

Anoushiravan R
Anoushiravan R

Reputation: 21938

You can also use the following solution. We use unquo or ensym function here to unquote a user-defined argument and then we use bang-bang !! operator on the LHS of := to force-evaluate it:

library(rlang)

collapsevars <- function(var, varcollapse){
  var <- enquo(var)
  
  mydata <- mydata %>%
    mutate(!!var := ifelse(rowSums(
      select(., all_of(varcollapse)) == "Yes") > 0,
      "Yes", "No"))
  
  mydata
}

collapsevars(afin, avars)

# A tibble: 20 x 7
   a1    a2    b1    b2       c1 afin  bfin 
   <fct> <fct> <fct> <fct> <dbl> <chr> <chr>
 1 No    Yes   Yes   Yes      10 Yes   Yes  
 2 N/A   N/A   N/A   No       14 No    No   
 3 No    No    No    Yes       9 No    Yes  
 4 No    No    N/A   No       14 No    No   
 5 No    No    Yes   N/A      10 No    Yes  
 6 No    N/A   N/A   Yes       8 No    Yes  
 7 No    N/A   N/A   Yes      13 No    Yes  
 8 No    N/A   Yes   No        9 No    Yes  
 9 N/A   N/A   Yes   No       11 No    Yes  
10 N/A   N/A   N/A   Yes      11 No    Yes  
11 Yes   Yes   No    Yes       9 Yes   Yes  
12 N/A   N/A   No    No        5 No    No   
13 No    N/A   Yes   Yes      10 No    Yes  
14 No    N/A   No    N/A       9 No    No   
15 N/A   No    No    Yes       8 No    Yes  
16 No    Yes   Yes   No       10 Yes   Yes  
17 No    N/A   No    No       11 No    No   
18 N/A   Yes   No    No       10 Yes   No   
19 N/A   N/A   N/A   No        7 No    No   
20 No    No    N/A   N/A       7 No    No  

Upvotes: 3

Ronak Shah
Ronak Shah

Reputation: 389235

You can use {{col}} := on left hand side in mutate -

library(dplyr)

collapsevars <- function(var, varcollapse){
  mydata <- mydata %>%
    mutate({{var}} := ifelse(rowSums(
      select(., all_of(varcollapse)) == "Yes") > 0,
      "Yes", "No"))
  mydata
}

collapsevars(afin, avars)

# A tibble: 20 x 6
#    a1    a2    b1    b2       c1 afin 
#   <fct> <fct> <fct> <fct> <dbl> <chr>
# 1 No    Yes   Yes   Yes      10 Yes  
# 2 N/A   N/A   N/A   No       14 No   
# 3 No    No    No    Yes       9 No   
# 4 No    No    N/A   No       14 No   
# 5 No    No    Yes   N/A      10 No   
# 6 No    N/A   N/A   Yes       8 No   
# 7 No    N/A   N/A   Yes      13 No   
# 8 No    N/A   Yes   No        9 No   
# 9 N/A   N/A   Yes   No       11 No   
#10 N/A   N/A   N/A   Yes      11 No   
#11 Yes   Yes   No    Yes       9 Yes  
#12 N/A   N/A   No    No        5 No   
#13 No    N/A   Yes   Yes      10 No   
#14 No    N/A   No    N/A       9 No   
#15 N/A   No    No    Yes       8 No   
#16 No    Yes   Yes   No       10 Yes  
#17 No    N/A   No    No       11 No   
#18 N/A   Yes   No    No       10 Yes  
#19 N/A   N/A   N/A   No        7 No 

Upvotes: 1

Related Questions