rjanitor

How to put tabyl(x, y) into a function in R?


I want to create a function with 3 arguments: df (dataframe) and 2 variables. And return a cross table. I can do it easily outside a function using tabyl. But how to do it using a function where I can select df and the 2 variables?

I suspect that this is a case of non-standard evaluation...

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(janitor)
#> 
#> Attaching package: 'janitor'
#> The following objects are masked from 'package:stats':
#> 
#>     chisq.test, fisher.test

mtcars %>%
  janitor::tabyl(vs, cyl)
#>  vs  4 6  8
#>   0  1 3 14
#>   1 10 4  0

# How can I put this into a function?

crTab <- function(df, v1, v2) {
  t <- df %>%
      tabyl(all_of(v1), all_of(v2))
  return(t)
}

crTab('mtcars', 'vs', 'cyl')
#> Error in tabyl.default(., all_of(v1), all_of(v2)): The value supplied to the "show_na" argument must be TRUE or FALSE.
#> 
#> Did you try to call tabyl on two vectors, like tabyl(data$var1, data$var2) ? To create a two-way tabyl, the two vectors must be in the same data.frame, and the function should be called like this: 
#> 
#>          tabyl(data, var1, var2)
#>          or
#>          data %>% tabyl(var1, var2).  
#> 
#> See ?tabyl for more.

Solution

  • If you want to pass column names in tidyverse setting use double curly brackets:

    "‘rlang’ uses NSE to capture the unevaluated argument and then checks whether the parse tree of the expression contains two nested { calls. It then takes the unevaluated expression and transforms it appropriately." taken from @Konrad Rudolph https://stackoverflow.com/questions/69454090/how-is-rlangs-curly-curly-operator-implemented#:~:text=The%20curly%2Dcurly%20operator%20%7B%7B,such%20as%20the%20data%20frame.

    library(dplyr)
    library(janitor)
    
    crTab <- function(df, v1, v2) {
      t <- df %>%
        tabyl({{v1}}, {{v2}})
      return(t)
    }
    
    crTab(mtcars, vs, cyl)
    
    vs  4 6  8
      0  1 3 14
      1 10 4  0