From ripley at stats.ox.ac.uk  Wed Jun 18 19:50:45 2003
From: ripley at stats.ox.ac.uk (Prof Brian Ripley)
Date: Wed Jun 18 19:50:58 2003
Subject: [Rd] update.default bugfix (PR#3288)
In-Reply-To: <200306181714.h5IHEDJH019663@pubhealth.ku.dk>
Message-ID: <Pine.LNX.4.44.0306181825510.1239-100000@gannet.stats>

Are you *sure* this is a bug, and not just how you would like it to be
to help with a misconception?

I can't see anything (including ?formula) which says that the formula
environment should be used, and I can think of quite a few situations
which this would break.  The idea of update.default is that it should be
the same as evaluating the revised call in the calling frame, and your
version doesn't do that.

On Wed, 18 Jun 2003 minka@stat.cmu.edu wrote:

> According to the man page for formula, "a formula object has an associated
> environment".  However, update.default doesn't use this environment, which
> creates problems like the following:
> 
>   make.model <- function(x) { lm(medv~.,x) }
>   library(MASS)
>   data(Boston)  
## not needed, BTW
>   fit = make.model(Boston)
>   fit = update(fit,".~.-crim")
>   # Object "x" not found

Yes, and I think that is correct.  This sort of thing is often done to 
fit against a different x.

Note that you are not even appealing to ?formula correctly. It says

     A formula object has an associated environment, and this
     environment (rather than the parent environment) is used by
     `model.frame' to evaluate variables that are not found in the
     supplied `data' argument.

and x is not such a variable (it is the `data' argument).

Now, had you done

make.form <- function(formula, data)
{
    env <- new.env()
    for(i in names(data)) assign(i, data[[i]], envir=env)
    environment(formula) <- env
    formula
}
form <- make.form(medv~age+black+crim, Boston)
fit <- lm(form)
update(fit, .~.-crim)

you *would* be making good use of the environment of the formula, and it 
does work.  I am pretty sure that is what ?formula is saying can be done.


> Here is a modification of update.default (from R 1.7.0) that fixes the
> problem.
> 
> Tom
> 
> update.default <-
>     function (object, formula., ..., evaluate = TRUE)
> {
>     call <- object$call
>     if (is.null(call))
>     stop("need an object with call component")
>     extras <- match.call(expand.dots = FALSE)$...
>     if (!missing(formula.))
>     call$formula <- update.formula(formula(object), formula.)
>     if(length(extras) > 0) {
>     existing <- !is.na(match(names(extras), names(call)))
>     ## do these individually to allow NULL to remove entries.
>     for (a in names(extras)[existing]) call[[a]] <- extras[[a]]
>     if(any(!existing)) {
>         call <- c(as.list(call), extras[!existing])
> 	    call <- as.call(call)
> 	    }
>     }
>     if(evaluate) {
>       # minka: use environment of formula instead of parent.frame
>       # see the man page for formula
>       env<-environment(call$formula)
>       if (is.null(env)) env<-parent.frame()
>       eval(call,env)
>     }
>     else call
> }
> 
> ______________________________________________
> R-devel@stat.math.ethz.ch mailing list
> https://www.stat.math.ethz.ch/mailman/listinfo/r-devel
> 

-- 
Brian D. Ripley,                  ripley@stats.ox.ac.uk
Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272866 (PA)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595


[Rd] update.default bugfix (PR#3288)
Prof Brian Ripley