Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mapply for all arguments' combinations [R]

Tags:

r

mapply

Consider this toy function that receives 3 arguments:

toy <- function(x, y, z){
    paste(x, y, z)
}

For each argument I have a number of values (not necessarily the same number for each argument) and I want to apply the toy function to the different combinations of those arguments.

So I thought, ok, let's use the multivariate version of the apply functions mapply.

mapply(FUN = toy, x = 1:2, y = c("#", "$"), z = c("a", "b"))

[1] "1 # a" "2 $ b"

But this is not quite what I wanted. Indeed, according to the help mapply "applies FUN to the first elements of each ... argument, the second elements, the third elements, and so on.". And what I want is to apply FUN to all the different combinations of all the arguments.

So, instead of

[1] "1 # a" "2 $ b"

The result I would like is rather:

[1] "1 # a" "1 # b" "1 $ a" "1 $ b" "2 # a" "2 # b" "2 $ a" "2 $ b"

So, my question is what is the clever way to do this?

Of course, I can prepare the combinations beforehand and arrange the arguments for mapply so they include -rowwise- all the combinations. But I just thought this may be a rather common task and there might be already a function, within the apply-family, that can do that.

like image 909
elikesprogramming Avatar asked Mar 09 '16 11:03

elikesprogramming


1 Answers

You could combine do.call with expand.grid to work with unlimited amount of input as follows

toy <- function(...) do.call(paste, expand.grid(...))

Then, you could do

x = 1:2 ; y = c("#", "$") ; z = c("a", "b")
toy(x, y, z)
# [1] "1 # a" "2 # a" "1 $ a" "2 $ a" "1 # b" "2 # b" "1 $ b" "2 $ b"

This will work for any input. You could try stuff like toy(x, y, z, y, y, y, z), for instance in order to validate.

like image 195
David Arenburg Avatar answered Nov 08 '22 16:11

David Arenburg