Charles C. Berry wrote: > 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.
I've changed the original example to: library(Design) attach(list(), name="design.options") on.exit(detach("design.options")) 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) assign('dd', datadist(d), pos='design.options') options(datadist="dd") lrm(ch ~ age, data=d, x=TRUE, y=TRUE) } fit(ch, age) This works when I paste it into the R console, but not when I source() the script: > library(Design) Loading required package: Hmisc ... > attach(list(), name="design.options") > on.exit(detach("design.options")) > 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) + assign('dd', datadist(d), pos='design.options') + options(datadist="dd") + lrm .... [TRUNCATED] > fit(ch, age) Error in as.environment(pos) : no item called "design.options" on the search list Or is that asking for too much? ;) -- Gad Abraham Dept. CSSE and NICTA The University of Melbourne Parkville 3010, Victoria, Australia email: [EMAIL PROTECTED] web: http://www.csse.unimelb.edu.au/~gabraham ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.