[Rd] Evaluation puzzle
Kevin R. Coombes
kevin.r.coombes at gmail.com
Thu Nov 11 23:31:35 CET 2010
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
More information about the R-devel
mailing list