Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split array arguments of a function using "..." R

The following function creates a data.frame with n columns as the number of arguments

functionWithDots <- function(...) {
  f1 <- function(x) c(x,x+4)
  list <- list(...)
  list <- lapply(list, f1)
  expand.grid(list)
  }

When running it as functionWithDots(1,2) The expected result is:

  • id Var1 Var2
    1. 1 2
    2. 5 2
    3. 1 6
    4. 5 6

while if I do the same by replacing "(1,2)" with "1:2" as

functionWithDots(1,2)

the result is

  • id Var1
    1. 1
    2. 2
    3. 5
    4. 6

How can I pass the correct unconcatenated argument to that functions since it seems to return different results when passing, let's say, "1,2,3" instead of "c(1,2,3)"?

like image 872
Federico Avatar asked Oct 20 '22 04:10

Federico


1 Answers

Assuming that I understood the problem correctly, ie. the OP wanted to get the same results by passing 1,2 and 1:2 in the functionWithDots, here is one way to fix it. We convert the elements in ... to list for both the cases and it should give the same result for both cases.

functionWithDots <- function(...) {
   f1 <- function(x) c(x,x+4)
   dots <- c(...)
   list <- as.list(dots)
   list <- lapply(list, f1)
   expand.grid(list)
 }


functionWithDots(1,2)
#  Var1 Var2
#1    1    2
#2    5    2
#3    1    6
#4    5    6
 functionWithDots(1:2)
#  Var1 Var2
#1    1    2
#2    5    2
#3    1    6
#4    5    6

Checking with 1:3 vs 1,2,3

functionWithDots(1,2,3)
#  Var1 Var2 Var3
#1    1    2    3
#2    5    2    3
#3    1    6    3
#4    5    6    3
#5    1    2    7
#6    5    2    7
#7    1    6    7
#8    5    6    7

functionWithDots(1:3)
#  Var1 Var2 Var3
#1    1    2    3
#2    5    2    3
#3    1    6    3
#4    5    6    3
#5    1    2    7
#6    5    2    7
#7    1    6    7
#8    5    6    7

Now, let's see the problem in the OP's function (removed the lapply and expand.grid)

functionWithDots <- function(...) {
  f1 <- function(x) c(x,x+4)
  list <- list(...)
  print(list)
}

In the first case 1:2, the function is returning a list of length 1

functionWithDots(1:2)
#[[1]]
#[1] 1 2

while in the second, it returns a list with length equal to the number of elements in the input

functionWithDots(1,2)
#[[1]]
#[1] 1

#[[2]]
#[1] 2

In the modified function, both are returning list with length equal to the number of elements in the input argument.

functionWithDots <- function(...) {
  f1 <- function(x) c(x,x+4)
  dots <- c(...)
  list <- as.list(dots)
  print(list) 
 }

functionWithDots(1:2)
#[[1]]
#[1] 1

#[[2]]
#[1] 2

functionWithDots(1,2)
#[[1]]
#[1] 1

#[[2]]
#[1] 2
like image 69
akrun Avatar answered Oct 21 '22 23:10

akrun