[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