Further delving into the mysteries of R evaluation...This is closely related to my previous question ( How to write an R function that evaluates an expression within a data-frame ). Let's say I want to write a function topfn that takes a data-frame and an expression involving column-names of that data-frame. I want to pass both these arguments on to another function fn that actually evaluates the expression within the "environment" of the data-frame. And I want both fn and topfn to work correctly when passed a data-frame and an expression
My first attempt, as suggested in the answer to the above question, is to define:
fn <- function(dfr, expr) {
mf <- match.call()
eval( mf$expr, envir = dfr )
}
And define topfn like this:
topfn <- function(df, ex) {
mf <- match.call()
fn(df, mf$ex)
}
Now if I have a data-frame
df <- data.frame( a = 1:5, b = 1:5 )
the inner function fn works fine:
> fn(df,a)
[1] 1 2 3 4 5
But the topfn does not work:
> topfn(df,a)
mf$ex
To fix this I first check the class of topfn(df,a),
> class(topfn(df,a))
[1] "call"
This gives me an idea for an ugly hack to re-define fn as follows:
fn <- function(dfr, expr) {
mf <- match.call()
res <- eval(mf$expr, envir = dfr)
if(class(res) == 'call')
eval(expr, envir = dfr) else
res
}
And now both functions work:
> fn(df,a)
[1] 1 2 3 4 5
> topfn(df,a)
[1] 1 2 3 4 5
As I said, this looks like an ugly hack. Is there a better way (or more standard idiom) to get these working? I've consulted Lumley's curiously-named Standard NonStandard Evaluation Rules document http://developer.r-project.org/nonstandard-eval.pdf but wasn't particularly enlightened after reading it. Also helpful would be any pointers to source-code of functions I can look at for examples.
fnandtopfnto work with the same types of inputs - and this a GOOD thing. - hadleyfn) when used in some other scenario -- I think that's what you're saying, right? - Prasad Chalasani