Re: [Rd] predict.smooth.spline.fit and Recall() (Was: Re: Return function from function and Recall())

From: Henrik Bengtsson <hb_at_maths.lth.se>
Date: Wed 05 Apr 2006 - 11:58:15 GMT

On 4/5/06, Prof Brian Ripley <ripley@stats.ox.ac.uk> wrote:
> On Wed, 5 Apr 2006, Henrik Bengtsson wrote:
>
> > Hi,
> >
> > forget about the below details. It is not related to the fact that
> > the function is returned from a function. Sorry about that. I've
> > been troubleshooting soo much I've been shoting over the target. Here
> > is a much smaller reproducible example:
> >
> > x <- 1:10
> > y <- 1:10 + rnorm(length(x))
> > sp <- smooth.spline(x=x, y=y)
> > ypred <- predict(sp$fit, x)
> > # [1] 2.325181 2.756166 ...
> > ypred2 <- predict(sp$fit, c(0,x))
> > # Error in Recall(object, xrange) : couldn't find
> > # function "predict.smooth.spline.fit"
>
> It seems Recall is not searching (via findFun) from the right environment,
> but at a quick glance it is not obvious to me why.
> You can replace Recall by predict.smooth.spline.fit for now.

More troubleshooting shows that by dispatching directly on 'sp' and not 'sp$fit' works. The reason that I do not want to do this is related to my questions yesterday that I want to keep the memory usage down and 'sp' hold quite some extra data even with keep.data=FALSE.

Example show how it works:

x <- 1:10
y <- 1:10 + rnorm(length(x))
sp <- smooth.spline(x=x, y=y)

The following two calls work:

ypred1 <- predict(sp, x)
ypred2 <- predict(sp, c(0,x))

They dispatch on predict.smooth.spline(), which in turn calls predict(sp$fit, ...) which dispatch on predict.smooth,spline.fit();

> getAnywhere("predict.smooth.spline")
A single object matching 'predict.smooth.spline' was found It was found in the following places
  registered S3 method for predict from namespace stats   namespace:stats
with value

function (object, x, deriv = 0, ...)
{

    if (missing(x)) {

        if (deriv == 0)
            return(object[c("x", "y")])
        else x <- object$x

    }
    fit <- object$fit
    if (is.null(fit))

        stop("not a valid \"smooth.spline\" object")     else predict(fit, x, deriv, ...)
}
<environment: namespace:stats>

Trying to do the same without the first step, that is, to call predict(sp$fit, ...) to dispatch on predict.smooth,spline.fit() directly, then the second will fail due to the Recall();

ypred3 <- predict(sp$fit, x)
ypred4 <- predict(sp$fit, c(0,x)) # Error!

Note that both predict.smooth.spline() and predict.smooth.spline.fit() are under the "namespace hood", i.e. not exported. So, no apparent difference there.

To avoid the overhead of some of the elements of 'sp' I create a minimal 'smooth.spline' object like this:

fit <- structure(list(fit=sp$fit), class=class(sp)) ypred5 <- predict(fit, x)
ypred6 <- predict(fit, c(0,x)) # Error!

and it all works. I don't really like to fake objects like this, although allowed in S3. But for now it's ok. However, it would be interesting to know/understands what is going on.

/Henrik

[snip]

> >
> > /Henrik
> >
> >
> > On 4/5/06, Henrik Bengtsson <hb@maths.lth.se> wrote:
> >> Hi,
> >>
> >> yesterday I got very useful feedback on what is the best way to return
> >> a function from a function.
> >>
> >> Now, I run into a problem calling a returned function that down the
> >> stream uses Recall(). Below is a self-contained example. I took away
> >> yesterday's code for returning a minimal environment for the function,
> >> because that is not related to this problem.
> >>
> >> getPredictor <- function(x, y) {
> >> sp <- smooth.spline(x=x, y=y, keep.data=FALSE)
> >> function(x, ...) predict(sp$fit, x, ...)$y
> >> }
> >>
> >> # Simulate data
> >> x <- 1:10
> >> y <- 1:10 + rnorm(length(x))
> >>
> >> # Estimate predictor function
> >> fcn <- getPredictor(x,y)
> >>
> >> # No extrapolation => no Recall()
> >> ypred <- fcn(x)
> >> print(ypred)
> >> # Gives: # [1] 2.325181 2.756166 ...
> >>
> >> # With extrapolation => Recall()
> >> xextrap <- c(0,x)
> >> ypred <- fcn(xextrap)
> >> # Gives: # Error in Recall(object, xrange) : couldn't find
> >> # function "predict.smooth.spline.fit"
> >>
> >> To see what's the function looks like, do
> >>
> >> pfcn <- getAnywhere("predict.smooth.spline.fit")$obj[[2]]
> >> page(pfcn)
> >>
> >> A workaround is to set the predict.smooth.spline.fit() in .GlobalEnv, i.e.
> >>
> >> predict.smooth.spline.fit <- pfcn
> >>
> >> Does Recall() have a problem because predict.smooth.spline.fit() is
> >> not exported, or what is going on? Are there alternatives to the
> >> above workaround? I can see how such a workaround can become very
> >> complicated with complex functions where it is hard to predict what
> >> functions are called when.
> >>
> >> /Henrik
> >>
> >> PS, may I suggest to modify page() so that
> >> 'page(getAnywhere("predict.smooth.spline.fit"))' works? DS.
> >>
> >
> >
> > --
> > Henrik Bengtsson
> > Mobile: +46 708 909208 (+2h UTC)
> >
> > ______________________________________________
> > R-devel@r-project.org mailing list
> > https://stat.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
>
>

--
Henrik Bengtsson
Mobile: +46 708 909208 (+2h UTC)

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Received on Wed Apr 05 22:22:21 2006

This archive was generated by hypermail 2.1.8 : Wed 05 Apr 2006 - 14:17:00 GMT