[R] eval and parent.frame [was: Error in Design package: dataset not found for options(datadist)]

Gad Abraham gabraham at csse.unimelb.edu.au
Sat Apr 19 03:30:46 CEST 2008


Charles C. Berry wrote:
> On Fri, 18 Apr 2008, Gad Abraham wrote:
> 
>> Frank E Harrell Jr wrote:
>>> Gad Abraham wrote:
>>>> Hi,
>>>>
>>>> Design isn't strictly an R base package, but maybe someone can explain
>>>> the following.
>>>>
>>>> When lrm is called within a function, it can't find the dataset dd:
>>>>
>>>> > library(Design)
>>>> > age <- rnorm(30, 50, 10)
>>>> > cholesterol <- rnorm(30, 200, 25)
>>>> > ch <- cut2(cholesterol, g=5, levels.mean=TRUE)
>>>> > fit <- function(ch, age)
>>>> + {
>>>> +    d <- data.frame(ch, age)
>>>> +    dd <- datadist(d)
>>>> +    options(datadist="dd")
>>>> +    lrm(ch ~ age, data=d, x=TRUE, y=TRUE)
>>>> + }
>>>> > fit(ch, age)
>>>> Error in Design(eval(m, sys.parent())) :
>>>>    dataset dd not found for options(datadist=)
>>>>
>>>> It works outside a function:
>>>> > d <- data.frame(ch, age)
>>>> > dd <- datadist(d)
>>>> > options(datadist="dd")
>>>> > l <- lrm(ch ~ age, data=d, x=TRUE, y=TRUE)
>>>>
>>>>
>>>> Thanks,
>>>> Gad
>>>
>>> My guess is that you'll need to put dd in the global environment, not in
>>> fit's environment.  At any rate it is inefficient to call datadist every
>>> time.  Why not call it once for the whole data frame containing all the
>>> predictors, at the top of the program?
>>
>> This is just sample code, in practice the datadist will be different for
>> each invocation of the function.
>>
>> I think it boils down to this behaviour, which I don't understand ---
>> although ls can see x in the parent of f2, eval cannot:
> 
> 
> That is because (from ?eval):
> 
> "Objects to be evaluated can be of types call or expression or name 
> (when the name is looked up in the current scope and its binding is 
> evaluated)..."
> 
> And 'x' is of type name (aka 'symbol').
> 
> So eval never gets around to looking in 'p', because it never succeeded 
> in looking up 'x' and evaluating its binding in the current scope.
> 
> What you probably want is
> 
>     b <- evalq( x, envir=p)
> 

Thanks, that solves the problem with this sample code, but not with the 
Design::lrm function, because there are several more layers of 
evaluation there.

I can get around that with the ugly hack of setting a global NULL 
datadist and assigning to it with "<<-" within the fit function every 
time, so it's always visible to Design. But it's still an ugly hack :)

-- 
Gad Abraham
Dept. CSSE and NICTA
The University of Melbourne
Parkville 3010, Victoria, Australia
email: gabraham at csse.unimelb.edu.au
web: http://www.csse.unimelb.edu.au/~gabraham



More information about the R-help mailing list