Another nice thing about using ~formula is that it stores the environment in which the formula was made along with the formula. Thus you know which envrionment should be used with evaluating it (and don't have to guess that parent.frame() may be the right environmnet). E.g., evalRHS <- function(formula) { RHS <- formula[[length(formula)]] eval(RHS, envir=environment(formula)) } p1 <- 1:3 p2 <- 11:13 f1 <- function(formula) { p1 <- 1000 evalRHS(formula) } f1(~p1+p2) # does not use the p1 defined in f1 # [1] 12 14 16 If you do want to override some of the variables in the formula you can do that by replacing the environment of the formula with a child of that environment. Do this in a function so it only replaces the environment in a copy of the formula, not the original one. f2 <- function(formula) { environment(formula) <- list2env(list(p1=1000), new.env(parent=environment(formula))) evalRHS(formula) } f2(~p1+p2) # [1] 1011 1012 1013 f1(~p1+p2) # [1] 12 14 16
(These examples are not the best since the global environment is searched in any case. Put the entire example inside a function to see the strength of the formula approach.) Bill Dunlap TIBCO Software wdunlap tibco.com On Tue, Sep 9, 2014 at 10:13 PM, David Winsemius <dwinsem...@comcast.net> wrote: > > On Sep 9, 2014, at 4:07 PM, peter dalgaard wrote: > >> >> On 07 Sep 2014, at 00:31 , David Winsemius <dwinsem...@comcast.net> wrote: >> >>> The goal: >>> to create a function modeled after `subset` (notorious for its >>> non-standard evaluation) that will take a series of logical tests as >>> unquoted expressions to be evaluated in the framework of a dataframe >>> environment and return a dataframe of logicals: >> >> ... >> >> A belated peep from the author of subset(): Don't! >> >> I think we learned the hard way by now that it is much easier to pass >> unevaluated expressions in the shape of formula objects or maybe expression >> objects. Lots of pain can be avoided by slipping in a simple "~". > > > It's taken me several years to understand why you are probably correct in > this regard. I needed to learn that `~` is actually a function that creates > a language object. > >> is.function(`~`) > [1] TRUE >> is.language( ~ x > 5 & x < 10) > [1] TRUE > > ... and that it's rather easy to extract the object somewhat like but not > really an expression embedded in such an object: > >> is.expression( ~ x > 5 & x < 10) > [1] FALSE > >> is.call( (~ x > 5 & x < 10)[2] ) > [1] TRUE > > The task of learning the various types of language objects is not an easy > one. > > -- > > David Winsemius, MD > Alameda, CA, USA > > ______________________________________________ > R-help@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. ______________________________________________ R-help@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.