NewBee
NewBee

Reputation: 1040

R functions: use argument as name within the function

I have created a user function in R to multiply two columns to create a third (within a series), so this function creates 4 new columns.

create_mult_var <- function(.data){
  .data <-.data%>%
    mutate(Q4_1_4 = Q4_1_2_TEXT*Q4_1_3_TEXT) %>% 
    mutate(Q4_2_4 = Q4_2_2_TEXT*Q4_2_3_TEXT) %>%
    mutate(Q4_3_4 = Q4_3_2_TEXT*Q4_3_3_TEXT) %>%
    mutate(Q4_4_4 = Q4_4_2_TEXT*Q4_4_3_TEXT)
  .data

I am trying to modify this function so that I can apply it to a different set of columns that match the same type. For instance, if I want to repeat this on the series of columns that start with "Q8", I know I can do the following:

create_mult_var_2 <- function(.data){
  .data <-.data%>%
    mutate(Q8_1_4 = Q8_1_2_TEXT*Q8_1_3_TEXT) %>% 
    mutate(Q8_2_4 = Q8_2_2_TEXT*Q8_2_3_TEXT) %>%
    mutate(Q8_3_4 = Q8_3_2_TEXT*Q8_3_3_TEXT) %>%
    mutate(Q8_4_4 = Q8_4_2_TEXT*Q8_4_3_TEXT)
  .data
  
}

Instead of creating a different function for each of the Q4 and Q8 series, I would like to add the "Q4" or "Q8" as an argument. I tried this below, but R would not accept this as an argument this way. Is there a way to achieve my desired outcome?

This does not work:

create_mult_var <- function(.data,question){
   .data <-.data%>%
   mutate(question_1_4 = question_1_2_TEXT*question_1_3_TEXT) %>% 
   mutate(question_2_4 = question_2_2_TEXT*question_2_3_TEXT) %>%
   mutate(question_3_4 = question_3_2_TEXT*question_3_3_TEXT) %>%
   mutate(question_4_4 = question_4_2_TEXT*question_4_3_TEXT)
  .data
   
}

I would like to modify the function, such as that I can use the following:

data_in %>% create_mult_var("Q4") %>% create_mult_var("Q8") 

Or something similar to create these new columns? Any suggestions are appreciated! Thank you! If this is a bad idea, any suggestions for how I should approach this?

Upvotes: 1

Views: 66

Answers (1)

akrun
akrun

Reputation: 886938

We could use paste and evaluate with !!

create_mult_var_2 <- function(.data, pat){
  .data <-.data%>%
    mutate(!! str_c(pat, '_1_4') :=
    !! rlang::sym(str_c(pat, '_1_2_TEXT')) *
    !! rlang::sym(str_c(pat, '_1_3_TEXT')))
  .data 
 }

create_mult_var_2(data_in, "Q4")
#  Q4_1_2_TEXT Q4_1_3_TEXT Q4_1_4
#1           1           5      5
#2           2           6     12
#3           3           7     21
#4           4           8     32

Also, based on the pattern showed, this can be automated as well

library(dplyr)
library(stringr)
create_mult_var_3 <- function(.data, pat) {
  .data %>%
    mutate(across(matches(str_c("^", pat, "_\\d+_2")), ~
               .* get(str_replace(cur_column(), '_2_TEXT', '_3_TEXT')),
         .names =  '{.col}_new')) %>%
    rename_at(vars(ends_with('_new')),
        ~ str_replace(., '\\d+_TEXT_new', '4'))



}

-testing

create_mult_var_3(data_in, "Q4")
#  Q4_1_2_TEXT Q4_1_3_TEXT Q4_1_4
#1           1           5      5
#2           2           6     12
#3           3           7     21
#4           4           8     32  
        

data

data_in <- data.frame(Q4_1_2_TEXT = 1:4, Q4_1_3_TEXT = 5:8)

Upvotes: 2

Related Questions