Randall Goodwin
2012-Jan-01 19:58 UTC
[R] How to pass in a list of variables as an argument to a function?
Hello,
I have some code that currently works fine and I am endeavoring to
convert the major pieces of it into functions.
This involves taking "hard coded" names of variables that are used in
various places and figuring out how to
abstract them out into functions where the arguments (i.e. a list of
variables)?can be passed to the parent function
and used within that function for various purposes.
Here is some code that comes close to replicating some of the cases I
am trying to solve.
Basically, the same list of variables comes up many times in the
current code (where nothing is really a function).
Now that I am converting everything to a function, I'd like to specify
the list of variables once and use that list
throughout the code in other places. The list of variables does not
have to be of class = list. more generally,
it could be any class that can be converted such that it is usable in
paste(), aggregate() and reshape() as in
the example below.
I have tried various things to make it work.. using paste() and
noquote() in combination to build a string that is identical to the
arguments that these functions accept, however R interprets them as a
string, not as individual arguments.
Thanks in advance,
Randall
#################################################################
# libraries used
library(reshape)
# create some data similar to use case
myData = data.frame(expand.grid(varA=c("a", "b",
"c"),
varB=c("d", "e", "f"),
varC=c("g", "h", "i"),
varD=c("old", "new")),
n=1000, fail=rbinom(2700,1000, 0.01))
# add in one more column
myData$pass = myData$n-myData$fail
# List of grouping vars. ?I would like to pass this object around and
use it as arguments in functions
myGroupVars = c("varA", "varB", "varC")
# create a new column that is the combination of the grouping vars
(used in plotting with lattice)
# Question 1: ?Is there a way to replace "varA, varB, varC" in the
function below with an object?
myData = transform(myData, groupVar = paste(varA, varB, varC, sep = " |
"))
# Sum the data by the same groupVars and two other variables
# Question 2: ?Is there a way to replace "varA + varB + varC" in the
function below and do the same aggregation?
myDataSum <- aggregate(cbind(pass, fail) ~ varA + varB + varC +
groupVar + varD, data = myData, sum)
# pivot the pass and fail quantity to one row per group, ?labelling them
# Question 3: ?This one actually works. ?idvar happily accepted the
vector of group vars. ?Better way?
myDataSum <- reshape(myDataSum, ?idvar = myGroupVars, v.names
c("pass", "fail"),
timevar = "varD", direction = "wide")
Joshua Wiley
2012-Jan-01 22:39 UTC
[R] How to pass in a list of variables as an argument to a function?
Hi Randall,
This will do it. There may be more elegant ways. Formula methods are
just handy front ends (e.g., stats:::aggregate.formula), that end up
dispatching to other methods usually. It is easy to pass a character
vector to extractor functions like `[`() so with a bit more typing,
you can often skip the formula altogether. I think that will be the
easiest approach if you are not actually typing the formula (there are
ways to create them, but bleh).
Cheers,
Josh
###########################################
# libraries used
library(reshape)
# create some data similar to use case
myData = data.frame(expand.grid(varA=c("a", "b",
"c"),
varB=c("d", "e", "f"),
varC=c("g", "h", "i"),
varD=c("old", "new")),
n=1000, fail=rbinom(2700,1000, 0.01))
# add in one more column
myData$pass = with(myData, n - fail)
# List of grouping vars. I would like to pass this object around and
use it as arguments in functions
myGroupVars = c("varA", "varB", "varC")
# create a new column that is the combination of the grouping vars
(used in plotting with lattice)
# Question 1: Is there a way to replace "varA, varB, varC" in the
function below with an object?
myData2 <- transform(myData, groupVar = do.call("paste", c(myData[,
myGroupVars], sep = " | ")))
myData = transform(myData, groupVar = paste(varA, varB, varC, sep = " |
"))
all.equal(myData, myData2)
# Sum the data by the same groupVars and two other variables
# Question 2: Is there a way to replace "varA + varB + varC" in the
function below and do the same aggregation?
myDataSum = aggregate(cbind(pass, fail) ~ varA + varB + varC +
groupVar + varD, data = myData, sum)
myDataSum2 <- aggregate(x = myData2[, c("pass", "fail")],
by = myData2[, c(myGroupVars, "groupVar", "varD")], FUN =
sum)
all.equal(myDataSum, myDataSum2)
# pivot the pass and fail quantity to one row per group, labelling them
# Question 3: This one actually works. idvar happily accepted the
vector of group vars. Better way?
myDataSum <- reshape(myDataSum, idvar = myGroupVars, v.names
c("pass", "fail"),
timevar = "varD", direction = "wide")
#####################################
On Sun, Jan 1, 2012 at 11:58 AM, Randall Goodwin
<randall.goodwin at gmail.com> wrote:> Hello,
>
> I have some code that currently works fine and I am endeavoring to
> convert the major pieces of it into functions.
> This involves taking "hard coded" names of variables that are
used in
> various places and figuring out how to
> abstract them out into functions where the arguments (i.e. a list of
> variables)?can be passed to the parent function
> and used within that function for various purposes.
>
> Here is some code that comes close to replicating some of the cases I
> am trying to solve.
>
> Basically, ?the same list of variables comes up many times in the
> current code (where nothing is really a function).
> Now that I am converting everything to a function, I'd like to specify
> the list of variables once and use that list
> throughout the code in other places. ?The list of variables does not
> have to be of class = list. ?more generally,
> it could be any class that can be converted such that it is usable in
> paste(), aggregate() and reshape() as in
> the example below.
>
> I have tried various things to make it work.. using paste() and
> noquote() in combination to build a string that is identical to the
> arguments that these functions accept, ?however R interprets them as a
> string, ?not as individual arguments.
>
> Thanks in advance,
>
> Randall
>
> #################################################################
>
> # libraries used
> library(reshape)
>
> # create some data similar to use case
> myData = data.frame(expand.grid(varA=c("a", "b",
"c"),
> varB=c("d", "e", "f"),
> varC=c("g", "h", "i"),
> varD=c("old", "new")),
> n=1000, fail=rbinom(2700,1000, 0.01))
>
> # add in one more column
> myData$pass = myData$n-myData$fail
>
> # List of grouping vars. ?I would like to pass this object around and
> use it as arguments in functions
> myGroupVars = c("varA", "varB", "varC")
>
> # create a new column that is the combination of the grouping vars
> (used in plotting with lattice)
> # Question 1: ?Is there a way to replace "varA, varB, varC" in
the
> function below with an object?
> myData = transform(myData, groupVar = paste(varA, varB, varC, sep = "
| "))
>
> # Sum the data by the same groupVars and two other variables
> # Question 2: ?Is there a way to replace "varA + varB + varC" in
the
> function below and do the same aggregation?
> myDataSum <- aggregate(cbind(pass, fail) ~ varA + varB + varC +
> groupVar + varD, data = myData, sum)
>
> # pivot the pass and fail quantity to one row per group, ?labelling them
> # Question 3: ?This one actually works. ?idvar happily accepted the
> vector of group vars. ?Better way?
> myDataSum <- reshape(myDataSum, ?idvar = myGroupVars, v.names >
c("pass", "fail"),
> timevar = "varD", direction = "wide")
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
--
Joshua Wiley
Ph.D. Student, Health Psychology
Programmer Analyst II, Statistical Consulting Group
University of California, Los Angeles
https://joshuawiley.com/