On Tue, 22 Apr 2008, Gad Abraham wrote: > 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? ;)
Well, I did say to use that bit of code IN your function. Like this: age <- rnorm(30, 50, 10) cholesterol <- rnorm(30, 200, 25) ch <- cut2(cholesterol, g=5, levels.mean=TRUE) fit <- function(ch, age){ on.exit(detach("design.options")) attach(list(), name="design.options") d <- data.frame(ch, age) assign('dd', datadist(d), pos='design.options') options(datadist="dd") lrm(ch ~ age, data=d, x=TRUE, y=TRUE) } print(fit(ch,age)) HTH, Chuck > > -- > 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. > Charles C. Berry (858) 534-2098 Dept of Family/Preventive Medicine E mailto:[EMAIL PROTECTED] UC San Diego http://famprevmed.ucsd.edu/faculty/cberry/ La Jolla, San Diego 92093-0901 ______________________________________________ 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.