0

I am trying to call a function, using a list containing two tibbles as arguments.

I've tried multiple ways (pmap, do.call, invoke, exec) but none seem to work. It seems that instead of using the two tibbles, the lists of the tibbles are used.

Example data:

list1 <- list(test1 = tibble(a = 1:3, b = 4:6), 
              test2 = tibble(c = 5:7, d = 7:9))
fun <- function(tbl1,tbl2) tbl1[1,] + tbl2[1,]

What i would like to get is:

print(magic_function_call(fun, list1))
> 6 11

Hardcoded without a function it would be like this:

list1$test1[1,] + list1$test2[1,]

What i get is:

pmap(list1,fun)

> Error in .f(test1 = .l[[1L]][[i]], test2 = .l[[2L]][[i]], ...) : 
  unused arguments (test1 = .l[[1]][[i]], test2 = .l[[2]][[i]])

do.call(fun,list1)

> Error in (function (tbl1, tbl2)  : 
  unused arguments (test1 = list(1:3, 4:6), test2 = list(5:7, 7:9))

 invoke(fun, list1)

> Error in (function (tbl1, tbl2)  : 
  unused arguments (test1 = list(1:3, 4:6), test2 = list(5:7, 7:9))

exec(fun, !!!list1)

> Error in (function (tbl1, tbl2)  : 
  unused arguments (test1 = list(1:3, 4:6), test2 = list(5:7, 7:9))

Doing it by hand works, but feels kinda clunky and as soon as I would want to use a dynamic list with different sizes I would run into problems again.

fun(list1$test1, list1$test2)
> 6 11

Is there any simple way to do this? Am I just missing something?

So to make it short: I want to give two tibbles in a list, as arguments for a function.

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • What is `magic_function_call()`? Is that where you're trying to fill in `pmap` or some other function? I think you're running into the [difference between `[` and `[[`](https://stackoverflow.com/q/1169456/5325862) – camille Aug 30 '19 at 21:21
  • @joran Thank you very much, That was the problem I overlooked! Do you know by any chance a way to to use do.call (or any other way) with non matching function argument names – Christian Ka Aug 30 '19 at 21:35
  • Yes, ``` fun <- function(...) ..1[1,] + ..2[1,] ``` Seems to be a good smoth way to do it. Thank you! – Christian Ka Aug 30 '19 at 21:51
  • If an answer solved your problem, accept it by clicking on the tick mark beside it; don't edit the question. – Hong Ooi Aug 30 '19 at 21:55
  • if the solution is the one you gave in the comments, then you can post the answer yourself. – Ben Bolker Aug 30 '19 at 21:59

2 Answers2

1

If you're willing to take your chances that the arguments are in the correct order (or if it doesn't matter),

do.call(fun,unname(list1))

works fine (when the arguments are unnamed, R uses positional matching for the arguments).

If you want to add the first rows of a list of an arbitrary number of tibbles, this would work:

sumfun <- function(...) { Reduce("+",
                          purrr::map(as.list(...),~.[1,]))}
sumfun(list1)

(there may be a "tidier" way to do it)

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
0

As posted by @joran:

If the names of list1 are tbl1 and tbl2 to match the function arguments, do.call works fine. As does invoke

You have to tell the function what list elements go with which arguments somehow, unless your only argument is ... which is maybe a better approach for what you're trying to do? Another (sort of roundabout) option would be to rename the list elements manually by grabbing the argument names with formalArgs()