Reputation: 11441
I want to use subset
within another function but to pass on the non-standard evaluation arguments from the top-level function. The following is non-working code, but outlines the idea:
foo_1 <- function(x, mysubset)
{
# some deparse, substitute etc. magic here ??
subset(x, subset)
}
foo_1(ansombe, x1 > 5)
I want this to get the same results as for subset(ansombe, x1 > 5)
. Also, I want the same to work when the argument is passed on to a deeper level, i.e.
foo_2 <- function(x, mysubset)
{
# some deparse, substitute etc. magic here ??
foo_1(x, mysubset)
}
foo_2(ansombe, x1 > 5)
Here also I want the same result as above.
What I have tried so far
I tried a substitute
-deparse
, eval
-parse
combination, like
foo_1 <- function(x, mysubset)
{
tx <- deparse(substitute(mysubset))
subset(x, eval(parse(text=tx)))
}
foo_1(anscombe, x1 >5)
This is fine, but how do I go on for foo_2
now?
Also, I remember the dictum by Thomas Lumley:
If the answer is parse() you should usually rethink the question. -- Thomas Lumley (R-help, February 2005)
So, I was wondering if there is a better approach than an eval
-parse
combination.?
Any ideas?
PS. This question is similar but does not include the deeper nesting: Pass subset argument through a function to subset
PPS: Maybe it is fruitful applying the .
function from plyr
, but I don't know how...
Upvotes: 2
Views: 656
Reputation: 206566
As long as you delay the evaulation as long as possible, something like this should work
foo_1 <- function(x, mysubset)
{
do.call("subset", list(quote(x), substitute(mysubset)))
}
foo_2 <- function(x, mysubset)
{
do.call("foo_1", list(quote(x), substitute(mysubset)))
}
data(anscombe)
foo_1(anscombe, x1 > 5)
foo_2(anscombe, x1 > 5)
but if you plan on mucking about with mysubset
you would need to be more careful.It would help to know exactly why you are doing this.
Upvotes: 2
Reputation: 132969
There might be dragons. (But those hide in subset
too.)
foo_1 <- function(x, mysubset)
{
sub <- eval(substitute(mysubset), envir=x, enclos=parent.frame())
x[sub,]
}
foo_1(iris, Sepal.Length == 5 & Species == "setosa")
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#5 5 3.6 1.4 0.2 setosa
#8 5 3.4 1.5 0.2 setosa
#26 5 3.0 1.6 0.2 setosa
#27 5 3.4 1.6 0.4 setosa
#36 5 3.2 1.2 0.2 setosa
#41 5 3.5 1.3 0.3 setosa
#44 5 3.5 1.6 0.6 setosa
#50 5 3.3 1.4 0.2 setosa
Upvotes: 4
Reputation: 52687
I don't think you can avoid eval
, but you can avoid parse
. Just reconstruct the call to subset
inside your function:
foo_1 <- function(x, mysubset) {
eval(call("subset", x, substitute(mysubset)), parent.frame())
}
foo_1(mtcars, cyl == 6 & mpg > 20)
# mpg cyl disp hp drat wt qsec vs am gear carb
# Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
# Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
# Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Upvotes: 2