0

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.
Sam Firke
  • 21,571
  • 9
  • 87
  • 105
sbac
  • 1,897
  • 1
  • 18
  • 31
  • 1
    You can already do this with `tabyl()`. Just `tabyl(mtcars, vs, cyl)` should get what you want. – Noah Aug 19 '22 at 12:09
  • See also https://stackoverflow.com/questions/66753999/how-to-use-tabyl-with-two-variables-within-a-function – Sam Firke Aug 19 '22 at 19:52

2 Answers2

2

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
TarJae
  • 72,363
  • 6
  • 19
  • 66
1

if you want to use quoted column names as arguments in your function (very useful when using in combination with lapply() or similar), then you need to write your function as follows:

pivot_table_fun = function(arg1, arg2) {
    janitor::tabyl(arg1, !!rlang::sym(arg2))
}

lapply(c("cyl", "gear"), \(x){pivot_table_fun(mtcars, x)})
#> [[1]]
#>  cyl  n percent
#>    4 11 0.34375
#>    6  7 0.21875
#>    8 14 0.43750
#> 
#> [[2]]
#>  gear  n percent
#>     3 15 0.46875
#>     4 12 0.37500
#>     5  5 0.15625
David Budzynski
  • 169
  • 1
  • 6