Reputation: 565
I have a function with 4 arguments:
my.function <- function(w,x,y,z){
w + x + y + z
}
I can give this function multiple values for z
:
> my.function(1,1,1,1:5)
[1] 4 5 6 7 8
But what if I want to give the function lists of values for w,x,y
and a vector of values for z
, such that the function will evaluate each set
of wxy.args
with each element of z
?
wxy.args <- list(set1 = list(w = 1.1, x = 2.1, y = 3.1),
set2 = list(w = 1.2, x = 2.2, y = 3.3),
set3 = list(w = 1.3, x = 2.3, y = 3.3))
z <- 1:5
Ideally, I would like to end up with a n x m
matrix, where n = set
and m = z
. For that reason, I wanted to use outer()
, but it doesn't seem like that is possible.
So, I guess this will involve one of the apply family or some combination of apply and do.call, but I'm struggling with it.
Thanks in advance!
Upvotes: 3
Views: 689
Reputation: 270268
To use outer
define my.function2
, a version of my.function
that takes z
and wxy
as two separate arguments, and then pass a vectorized version of it to outer
:
my.function2 <- function(z, wxy) do.call(my.function, c(wxy, z))
outer(z, wxy.args, Vectorize(my.function2))
giving:
set1 set2 set3
[1,] 7.3 7.7 7.9
[2,] 8.3 8.7 8.9
[3,] 9.3 9.7 9.9
[4,] 10.3 10.7 10.9
[5,] 11.3 11.7 11.9
Another equivalent possibility that is simpler but slightly more tedious is to write out the arguments to my.function
using this version of my.function2
instead:
my.function2 <- function(z, wxy) my.function(wxy[[1]], wxy[[2]], wxy[[3]], z)
Upvotes: 1
Reputation: 132969
You can use mapply
to iterate over your sets. It iterates over the list elements. I use do.call
to pass the sublists to my.function
:
mapply(function(...) do.call(my.function, c(list(z = z), ...)),
wxy.args)
# set1 set2 set3
#[1,] 7.3 7.7 7.9
#[2,] 8.3 8.7 8.9
#[3,] 9.3 9.7 9.9
#[4,] 10.3 10.7 10.9
#[5,] 11.3 11.7 11.9
Use t
to transpose the matrix if necessary.
Upvotes: 4
Reputation: 5232
library(purrr)
wxy.args %>% map(~c(.x, z = list(z))) %>%
map(~do.call("my.function", args = .x)) %>%
unlist() %>%
matrix(nrow = length(wxy.args), byrow = TRUE)
gives:
[,1] [,2] [,3] [,4] [,5]
[1,] 7.3 8.3 9.3 10.3 11.3
[2,] 7.7 8.7 9.7 10.7 11.7
[3,] 7.9 8.9 9.9 10.9 11.9
Upvotes: 1
Reputation: 40171
One option could be:
sapply(z, function(x) lapply(wxy.args, function(y) sum(unlist(y), x)))
[,1] [,2] [,3] [,4] [,5]
set1 7.3 8.3 9.3 10.3 11.3
set2 7.7 8.7 9.7 10.7 11.7
set3 7.9 8.9 9.9 10.9 11.9
Upvotes: 1