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

Charles C. Berry cberry at tajo.ucsd.edu
Sat Apr 19 23:31:02 CEST 2008


On Sat, 19 Apr 2008, Gad Abraham wrote:

> 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 :)

Well, the ultimate problem is here

<from Design>
   XDATADIST <- .Options$datadist
     if (length(XDATADIST)) {
         if (!exists(XDATADIST))
             stop(paste("dataset", XDATADIST, "not found for options(datadist=)"))
...

exists()  mandates that there be an object as.name(XDATADIST) in the 
search() list. And a further eval(as.name(XDATADIST)) also requires this.

Another way to do make your function work is to use this in it:

 	on.exit( detach("design.options") )
 	attach(list(), name= "design.options" )
 	d <- data.frame(ch, age)
    	assign('dd', datadist(d), pos='design.options')

Admittedly still a hack, but it keeps your function from messing 
around with .GlobalEnv, and unless you are willing to rewrite lrm and 
Design, this is what you are stuck with.

HTH,

Chuck

>
> -- 
> 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
>
>

Charles C. Berry                            (858) 534-2098
                                             Dept of Family/Preventive Medicine
E mailto:cberry at tajo.ucsd.edu	            UC San Diego
http://famprevmed.ucsd.edu/faculty/cberry/  La Jolla, San Diego 92093-0901



More information about the R-help mailing list