0

I have a function in R that takes in 3 parameters, say foo(x,y,z).

When I call the function, I really have a list of elements for x, and a list for y but only one element for z. If Z was a list, and I wanted to apply foo to each element, mapply(foo, x, y, z) works.

However, since z is not a list, mapply(foo,x,y,z) does not work.

More specifically, if x and y are lists of 3 elements each, the following does work however: mapply(foo, x, y, list(z, z, z)).

Is there a way I can perhaps combine mapply and sapply without me first making z into a list of 3 elements? I want z to just be reused!

Edit 1: I was asked for an example:

mylist1 <- list(c(5,4), c(7,9), c(8,3))
mylist2<- list(c(2,3), c(6,7), c(10,11))
item3 <- matrix(data = 15, nrow = 3, ncol = 3)
foo <- function(x,y,z){
       return(x[1]+y[2]+z[2,2])
}

The following works:

> mapply(foo, mylist1, mylist2, list(item3,item3, item3))
[1] 23 29 34

The following does not work:

mapply(foo, mylist1, mylist2, item3)
Error in z[2, 2] : incorrect number of dimensions
Jilber Urbina
  • 58,147
  • 10
  • 114
  • 138
user1357015
  • 11,168
  • 22
  • 66
  • 111
  • 1
    I don't think I follow. The documentation at `?mapply` states that arguments are extended via recycling. Can you construct a concrete example that illustrates your problem? – joran Aug 30 '12 at 00:51

2 Answers2

4

Use the MoreArgs argument to mapply

mapply(foo, x = mylist1, y= mylist2, MoreArgs = list(z = item3))
## [1] 23 29 34
mnel
  • 113,303
  • 27
  • 265
  • 254
  • This is basically identical to (but more typing than) what I proposed. – joran Aug 30 '12 at 01:26
  • Yes, however I'm not sure if it is the same, does your solution evaluate `list(item3)` as the MoreArgs argument, or as part of the `...`? Does it matter? Regardless I think it is good practice to name the arguments for readability. I'm more than happy to add my answer as an edit to yours if they are evaluating to the same thing – mnel Aug 30 '12 at 01:47
  • Oh, I'm not complaining! I'm pretty sure that if you don't name `list(item3)` it gets evaluated with `...`, but I don't know if there's a performance cost in forcing that vectorization via recycling. Indeed, I'm not sure how R handles the MoreArgs piece internally. – joran Aug 30 '12 at 01:56
  • See this related post which delves into that question a bit further: https://stackoverflow.com/questions/56443892/mapply-with-multiple-arguments-where-one-argument-is-constant-data – Dominic Comtois Jan 23 '21 at 01:27
2

You just have to put the last item in a list, and R will recycle it just fine:

mapply(foo, mylist1, mylist2, list(item3))

Note that the documentation specifically says that the arguments you pass need to be:

arguments to vectorize over (vectors or lists of strictly positive length, or all of zero length)

and you were trying to pass a matrix.

joran
  • 169,992
  • 32
  • 429
  • 468