Reputation: 61
I have several data objects (three-dimensional arrays), for example object1, object2, object3.
These objects are listed in a character vector:
char <- c("object1","object2","object3")
I then need to grab the list of objects for use in a function that requires its inputs to be separated by commas:
output <- FancyFunction(object1,object2,object3,OtherFancyStuff)
How can I get R to automatically change the lower line of code when I change the upper line of code? I want to be able to add or delete objects from "char" and have it change accordingly in "output".
I don't know how to do this. The best I can do is:
output <- FancyFunction(get(char[1]),get(char[2]),get(char[3]),OtherFancyStuff)
But this is useless if the size of char changes.
Any thoughts?
Upvotes: 2
Views: 1701
Reputation: 206232
The function do.call
let's you call a function by passing a list of parameter values. In this case, you just need to create a list of the objects you want to pass and any additional parameters.
Since you already have the names of the objects you want to include in character vector form, the function mget()
will return a list of objects with those names so that part is easy. You just need to add in your additional parameters.
So you can call your function with
do.call( FancyFunction, c(mget(char),OtherFancyStuff) )
Upvotes: 2
Reputation: 174813
I suppose something like this will work:
char <- c("object1","object2","object3")
## 2-d objects for illustration as I couldn't think of an array
## function that took arbitrary input vectors `...`
object1 <- object2 <- object3 <- array(1:25, dim = c(5,5))
do.call("rbind", mget(char))
which gives
> do.call("rbind", mget(char))
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
[6,] 1 6 11 16 21
[7,] 2 7 12 17 22
[8,] 3 8 13 18 23
[9,] 4 9 14 19 24
[10,] 5 10 15 20 25
[11,] 1 6 11 16 21
[12,] 2 7 12 17 22
[13,] 3 8 13 18 23
[14,] 4 9 14 19 24
[15,] 5 10 15 20 25
To pass in extra arguments, you need to modify this slightly, by concatenating the other arguments on the object returned by mget(char)
, for example:
c(mget(char), list(arg1 = "foo", arg2 = "bar", arg3 = 1:10))
> c(mget(char), list(arg1 = "foo", arg2 = "bar", arg3 = 1:10))
$object1
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
$object2
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
$object3
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
$arg1
[1] "foo"
$arg2
[1] "bar"
$arg3
[1] 1 2 3 4 5 6 7 8 9 10
where arg1
etc correspond to additional arguments needed by FancyFunction
and need to be named as per the formal arguments you wish these to map to in the definition of FancyFunction
. The call would then resemble:
OtherFancyStuff <- list(arg1 = "foo", arg2 = "bar", arg3 = 1:10)
do.call("FancyFunction", c(mget(char), OtherFancyStuff)
Does FancyFunction
need 3 arguments or is it's first argument ...
? If you have control over this, it might be worth rewriting FancyFunction
to take ...
as the first argument and extract out of it the various arguments, any number of which can now be supplied:
FancyFunction <- function(..., other) {
dots <- list(...)
## work on components of 'dots', the length of which is number of args
## provided as ...
....
return()
}
Upvotes: 5