Re: [Rd] Evaluation puzzle

From: Kevin R. Coombes <kevin.r.coombes_at_gmail.com>
Date: Thu, 11 Nov 2010 16:31:35 -0600

Hi Terry,

This may not really be a complete answer, but there seems to be a difference in eval'ing an expression compared to eval'ing a call (even though both are documented in the help page for eval as working just fine).

If you insert the line

     print(eval(expression(zed), parent.frame())) into your survexp.test function just above the existing call to "eval", this line works just fine. So it's clear that an _expression_ containing "zed" can be evaluated, but evaluating the _call_ via the model.frame function fails.

I suspect that the actual evaluation problem lies in the call to

     eval(predvars, data, env)
made inside model.frame.default. The value of "env" when this function is called is defined in an earlier line by

     env <- environment(formula)
Since the formula does not have an environment defined when it is passed in, one gets provided within the model.frame.default function. I edited my version of model.frame.default to

     print(ls(env))
just before the call to

     eval(predvars, data, env)
and confirmed that "zed" is not part of that environment.

Now the manual page for formula says that "Formulas created with ~ use the environment in which they were created. Formulas created with 'as.formula' use the env argument for their environment." Since you are passing a character string through to model.frame, and it calls "as.formula" without an environment, the formula eventually gets evaluated in the context of the model.frame.default function without knowing about the environment you gave it.

I think you can fix this by explicitly creating your own formula+environment before calling miodel frame. Specifically, try changing the line

     m$formula <- tform
to

     m$formula <- as.formula(tform, env=parent.frame()) and see if that helps. On my machine, it at least allows

     tfun(tdata)
to run without throwing an error.

Best,

     Kevni

On 11/11/2010 2:08 PM, Terry Therneau wrote:
> The survexp function can fail when called from another function. The "why" of
> this has me baffled, however.
>
> Here is a simple test case, using a very stripped down version of survexp:
>
> survexp.test<- function(formula, data,
> weights, subset, na.action, rmap,
> times, cohort=TRUE, conditional=FALSE,
> ratetable=survexp.us, scale=1, npoints, se.fit,
> model=FALSE, x=FALSE, y=FALSE) {
> call<- match.call()
> m<- match.call(expand.dots=FALSE)
>
> # keep the first element (the call), and the following selected arguments
> m<- m[c(1, match(c('formula', 'data', 'weights', 'subset', 'na.action'),
> names(m), nomatch=0))]
> m[[1]]<- as.name("model.frame")
>
> # Add in the ratetable variables
> varlist<- attr(ratetable, 'dimid')
> tform<- paste(deparse(formula), paste(varlist, collapse='+'), sep='+')
> m$formula<- tform
>
> print(m)
> print(ls(parent.frame()))
> mf<- eval(m, parent.frame())
>
> names(mf)
> }
>
> Here is the test data
>
> tdata<- data.frame(age= c(12, 24, 36)*365.25, sex=c(1,2,1),
> year=as.Date('1953/03/10', '1960/02/23', '1978/09.22'))
> tfun<- function(mydata) {
> zed<- 100 + (1:nrow(mydata)) * 20
> survexp.test(zed ~ 1, data=mydata)
> }
>
> And the result of the exercise.
>
> % R --vanilla
> R version 2.11.0 (2010-04-22)
>
>> library(survival) # to pick up the survexp.us data
>> tfun(tdata)
> model.frame(formula = "zed ~ 1+age+sex+year", data = mydata)
> [1] "mydata" "zed"
> Error in eval(expr, envir, enclos) : object 'zed' not found
>
> -----
> Eval is being called with the expression shown and an environment that
> contains the relevant variables in that expression: zed and mydata. Yet it
> fails to find the variable zed.
>
> I don't see anything relevant in the manual pages for either eval or
> model.frame. I suspect that there is an invisible, undocumented, magic
> argument somewhere.
>
>
> My second problem is a puzzler:
>
>> options(error=recover)
>> tfun(tdata)
> model.frame(formula = "zed ~ 1+age+sex+year", data = mydata)
> [1] "mydata" "zed"
> Error in eval(expr, envir, enclos) : object 'zed' not found
>
> Enter a frame number, or 0 to exit
>
> 1: tfun(tdata)
> 2: survexp.test(zed ~ 1, data = mydata)
> 3: eval(m, parent.frame())
> 4: eval(expr, envir, enclos)
> 5: model.frame(formula = "zed ~ 1+age+sex+year", data = mydata)
> 6: model.frame.default(formula = "zed ~ 1+age+sex+year", data = mydata)
> 7: eval(predvars, data, env)
> 8: eval(expr, envir, enclos)
>
> Selection: 2
> Called from: model.frame.default(formula = "zed ~ 1+age+sex+year", data = mydata)
>
>
> Why does selecting "2" result in going to frame "6"?
>
> Terry Therneau
>
> ______________________________________________
> R-devel_at_r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Thu 11 Nov 2010 - 22:34:34 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Thu 11 Nov 2010 - 23:30:19 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.

list of date sections of archive