[R] function problem: multi selection in one argument

Martin Maechler m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Tue Jan 25 16:10:40 CET 2022


>>>>> Rui Barradas 
>>>>>     on Tue, 25 Jan 2022 14:22:47 +0000 writes:

    > Hello,
    > Here are 3 functions that do what the question asks for. The first 2 are 
    > tidyverse solutions, the last one a base R function.

    > I don't understand why the group_by and mutate, that's why I've included 
    > a 2nd tidyverse function. And the base R function follows the same lines 
    > of outputing the table only without data transformation.

    > And the test dataset is not iris, it only has one factor variable. It 
    > doesn't make sense to table a continuous variable such as Petal.Width.

    > The data set mtcars has several numeric variables that are in fact 
    > categorical ("vs", "am") and one, "cyl", that can be tabled. The 
    > examples below use mtcars.



    > f3 <- function(data, ...){
    >   groups <- unlist(list(...))
    >   temp <- data %>%
    >     select(all_of({{groups}})) %>%
    >     group_by(across(all_of({{groups}}))) %>%
    >     mutate(numbering = row_number(), max = n())
    >   temp %>%
    >     select(all_of({{groups}})) %>%
    >     table()
    > }

    > f4 <- function(data, ...){
    >   groups <- unlist(list(...))
    >   data %>%
    >     select(all_of({{groups}})) %>%
    >     table()
    > }

    > f5 <- function(data, ...){
    >   temp <- lapply(list(...), \(col) data[[col]])
    >   table(setNames(temp, list(...)))
    > }

    > f3(mtcars, "am", "cyl")
    > f4(mtcars, "am", "cyl")
    > f5(mtcars, "am", "cyl")

    > Hope this helps,
    > Rui Barradas

Thank you, Rui!

Note that your base R solution can be vastly simplified :

> f6 <- function(data, ...) table(data[, unlist(list(...))])
> f6(mtcars, "am", "cyl")
   cyl
am   4  6  8
  0  3  4 12
  1  8  3  2
> 

If you started measuring carefully, I'm sure this would not only
be the shortest but also by far the fastest solution ...

Best,
Martin

--
Martin Maechler
ETH Zurich  and   R Core Team


    > Às 00:14 de 25/01/2022, Kai Yang via R-help escreveu:
    >> Hello Team,
    >> I can run the function below:
    >> 
    >> library(tidyverse)
    >> 
    >> f2 <- function(indata, subgrp1){
    >>   indata0 <- indata
    >>   temp    <- indata0 %>% select({{subgrp1}}) %>% arrange({{subgrp1}}) %>%
    >>     group_by({{subgrp1}}) %>%
    >>     mutate(numbering =row_number(), max=max(numbering))
    >>   view(temp)
    >>   f_table <- table(temp$Species)
    >>   view(f_table)
    >>   return(f_table)
    >> }
    >> f2(iris, Species)
    >> 
    >> You can see the second argument I use Species only, and it works fine.
    >> But If I say, I want the 2nd argument = Petal.Width, Species , how should I write the argument? I did try f2(iris, c(Petal.Width, Species)), but I got error message:
    >> Error: arrange() failed at implicit mutate() step.
    >> * Problem with `mutate()` column `..1`.
    >> i `..1 = c(Petal.Width, Species)`.
    >> i `..1` must be size 150 or 1, not 300.
    >> 
    >> I'm not sure how to fix the problem either in function or can fix it when using the function.
    >> Thank you,
    >> Kai
    >> [[alternative HTML version deleted]]
    >> 
    >> ______________________________________________
    >> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
    >> https://stat.ethz.ch/mailman/listinfo/r-help
    >> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
    >> and provide commented, minimal, self-contained, reproducible code.

    > ______________________________________________
    > R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
    > https://stat.ethz.ch/mailman/listinfo/r-help
    > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
    > and provide commented, minimal, self-contained, reproducible code.



More information about the R-help mailing list