Michael Bedward
2010-Sep-15 06:07 UTC
[R] retrieving object names passed indirectly to a function
Hi folks,
I'm stuck with a problem that I suspect has a trivial solution...
I have a function, call it foo, that takes a number of arguments which
it uses as parameters for a simulation. For later analysis, foo stores
the names of the objects passed to it along with the simulation
results in its output (written to a database). The objects names are
accessed with deparse(substitute(argname)).
A second function, call it foo.driver, takes as input a data.frame
with cols corresponding to foo arguments containing the character
names of objects. For each row of the data.frame in turn, it retrieves
the required objects from the global environment and passes them to
function foo.
Where I am stuck is in how foo.driver should pass an object to foo
such that calling deparse(substitute(argname)) in foo will retrieve
the correct name (ie. that specified in foo.driver's input
data.frame).
Hopefully, the following toy code example illustrates what I'm trying to
do...
# some objects in the global environment to provide param values to foo
p1.1 <- 1
p1.2 <- 2
p2.1 <- 3
p2.2 <- 4
# controlling table
arg.table <- data.frame(p1=c("p1.1", "p2.2"),
p2=c("p2.1", "p2.2"),
replicates=c(100, 100))
foo.driver <- function( arg.table ) {
for (i in 1:nrow(arg.table)) {
for (j in 1:arg.table$replicates[i]) {
# somehow retrieve objects named in cols p1 and p2 and
# pass them to foo with their original names
# (e.g. some clever use of get and assign ?)
}
}
}
foo <- function(p1, p2) {
# retrieve and store arg names
p1name <- deparse(substitute(p1))
p2name <- deparse(substitute(p2))
# run simulation with values of p1 and p2 then
# store results together with names of objects
# passed as args to output database
}
My actual simulation function involves a large number of arguments of
various classes and if at all possible I prefer to avoid hacking it
(e.g to accept object names rather than objects).
Any tips much appreciated.
Michael
Michael Bedward
2010-Sep-15 12:28 UTC
[R] retrieving object names passed indirectly to a function
Answering my own question (in case it's of use to anyone else) here is
the example code again but now using call and eval to accomplish the
desired output:
foo <- function(p1, p2) {
p1name <- deparse(substitute(p1))
p2name <- deparse(substitute(p2))
# The real function runs a simulation, but
# here we just confirm the object names
# and values passed as args
cat("passed", p1name, "with value", p1, "\n")
cat("passed", p2name, "with value", p2, "\n")
}
foo.driver <- function(param.table) {
for (i in 1:nrow(param.table)) {
foo.call <- call("foo",
as.name(param.table$p1[i]),
as.name(param.table$p2[i]) )
for (rep in 1:param.table$repl[i]) {
eval(foo.call)
}
}
}
# some objects in the global env which will be used as args to foo
p1a <- 1.1
p1b <- 1.2
p2a <- 2.1
p2b <- 2.2
# the controlling table for foo.driver
param.table <- data.frame(p1=c("p1a", "p1b"),
p2=c("p2a","p2b"),
replicates=c(1,1), stringsAsFactors=FALSE)
# Now run foo.driver with param.table...
foo.driver(param.table)
The code above produces the following output:
passed p1a with value 1.1
passed p2a with value 2.1
passed p1b with value 1.2
passed p2b with value 2.2
Happy :)
Michael
On 15 September 2010 16:07, Michael Bedward <michael.bedward at gmail.com>
wrote:> Hi folks,
>
> I'm stuck with a problem that I suspect has a trivial solution...
>
> I have a function, call it foo, that takes a number of arguments which
> it uses as parameters for a simulation. For later analysis, foo stores
> the names of the objects passed to it along with the simulation
> results in its output (written to a database). The objects names are
> accessed with deparse(substitute(argname)).
>
> A second function, call it foo.driver, takes as input a data.frame
> with cols corresponding to foo arguments containing the character
> names of objects. For each row of the data.frame in turn, it retrieves
> the required objects from the global environment and passes them to
> function foo.
>
> Where I am stuck is in how foo.driver should pass an object to foo
> such that calling deparse(substitute(argname)) in foo will retrieve
> the correct name (ie. that specified in foo.driver's input
> data.frame).
>
> Hopefully, the following toy code example illustrates what I'm trying
to do...
>
> # some objects in the global environment to provide param values to foo
> p1.1 <- 1
> p1.2 <- 2
> p2.1 <- 3
> p2.2 <- 4
>
> # controlling table
> arg.table <- data.frame(p1=c("p1.1", "p2.2"),
p2=c("p2.1", "p2.2"),
> replicates=c(100, 100))
>
> foo.driver <- function( arg.table ) {
> ?for (i in 1:nrow(arg.table)) {
> ? ?for (j in 1:arg.table$replicates[i]) {
> ? ? ?# somehow retrieve objects named in cols p1 and p2 and
> ? ? ?# pass them to foo with their original names
> ? ? ?# (e.g. some clever use of get and assign ?)
> ? ?}
> ?}
> }
>
> foo <- function(p1, p2) {
> ?# retrieve and store arg names
> ?p1name <- deparse(substitute(p1))
> ?p2name <- deparse(substitute(p2))
>
> ?# run simulation with values of p1 and p2 then
> ?# store results together with names of objects
> ?# passed as args to output database
> }
>
> My actual simulation function involves a large number of arguments of
> various classes and if at all possible I prefer to avoid hacking it
> (e.g to accept object names rather than objects).
>
> Any tips much appreciated.
>
> Michael
>