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 >