Search code examples
rfunctiondplyrquosure

R: In a function using dplyr, how do I check to make sure that an argument name is not quoted before proceeding?


Long story, short: I have a function where the argument grouping.var = record_id will work, but grouping.var = "record_id" will return incorrect data with no error. So I want my function to check that the name passed to the argument is not in quotes.

Long story, long: I often have data where each research subject will have multiple visits with each visit corresponding to a row. Some data that doesn't change between visits (such as ethnicity or sex) only appears on one row. My function will copy the data from the variables I feed it to all rows for that subject.

mash <- function(data, variables, grouping.var){
   data <- data %>%
     dplyr::arrange(!!rlang::enquo(grouping.var))%>%
     dplyr::group_by(!!rlang::enquo(grouping.var))%>%
     dplyr::mutate_at(dplyr::vars(!!!variables),
                function(x) zoo::na.locf(x[order(x)], na.rm = F))%>%
     dplyr::ungroup()
   return(data)
}
df <- tibble(record_id = c('A', 'A', 'A', 'B', 'B', 'C', 'C', 'C'),
             x = c(NA, 1, NA, 2, NA, NA, NA, 3),
             y = c(1, NA, NA, NA, 2, 3, NA, NA))
df
df.2 <- mash(df, c('x','y'), grouping.var = record_id) #This works fine.
df.2

If I accidently quote the grouping.var, it will return wrong data without an error.

df.3 <- mash(df, c('x','y'), grouping.var = 'record_id') #does not work

This could cause major trouble for me if I don't catch the mistake. So I would like to add a check to determine if the the name passed to that argument is in the correct format.

I've tried if(is.character(grouping.var)), if(is_quosure(grouping.var)), and if(is.object(grouping.var)) statements but if the grouping.var is not quoted (ie in the correct format), it will return an error. I need something that will stop the function if the name is in quotes, but allow it to continue if it is not in quotes.

I admit that quosures in general confuse the heck out of me, so I could use some help on this one. Other solutions to the main problem are also welcome.


Solution

  • You can use the .data[[foo]] function, first enquo the variable. Programming with dplyr

    mash <- function(data, variables, grouping.var){
    
    grouping.var = enquo(grouping.var)
    
     data %>%
      dplyr::arrange(.data[[grouping.var]]) %>%
      dplyr::group_by(.data[[grouping.var]]) %>%
      dplyr::mutate_at(dplyr::vars(!!!variables),
                     function(x) zoo::na.locf(x[order(x)], na.rm = F))%>%
      dplyr::ungroup()
    
    }