pbreheny / visreg

Visualization of regression functions
http://pbreheny.github.io/visreg/
61 stars 18 forks source link

Specifying the range of a plot #124

Open barryrowlingson opened 1 month ago

barryrowlingson commented 1 month ago

I'm fitting an mgcv::gam model over a map using a formula likeP ~ s(X,Y) term where X and Y are the geographic coordinates of the data. visreg2d(model, "X","Y") does a great job of making a plot of the fitted smoother, but the X and Y range only extend to the min-max of X and Y.

What I want to do is extend that to cover a geographic border that extends outside the range of the X and Y data, in order to then crop it to the border to make a neat map. Yes, I know extrapolation outside the data like this is probably a bad idea but with consideration of errors etc its not a problem...

Currently the ranges are set in visreg:::setupV2:

    xx <- if (is.factor(x)) 
        factor(levels(x), levels = levels(x))
    else seq(min(x), max(x), length = nn)
    yy <- if (is.factor(y)) 
        factor(levels(y), levels = levels(y))
    else seq(min(y), max(y), length = nn)

and as a quick hack I modified this with an extra parameter specifying an extra offset to subtract from the minimum value and add to the maximum. Not very nice but works for me.

Ideally I might want to specify the expanded xydf grid directly:

xydf <- as.data.frame(expand.grid(xx, yy))

since I might want to do a grid with precise, eg 1000x1000, step size. At some point it might just be easier for me to write the code to return the model predictions on the grid without using visreg, but being able to specify variable ranges for plotting directly in the visreg functions might be generally useful for others too.

pbreheny commented 1 month ago
  1. I'm not sure what you mean by "I might want to do a grid with precise, eg 1000x1000, step size"; can't you already control the step size?
  2. Extrapolation: Hmmm...I guess I could support something like this with a warning if you specify limits outside the range of the data.
barryrowlingson commented 1 month ago

almost... if I can control the limits of the xvar range and specify nn correctly I can get a series with any step size. eg suppose I want a step size of 1 and an origin at 0. My xvar data range is 0.2 to 9.8, if I can extend the range to 0 to 10 then set nn to 11 then I'll get a sequence with stepsize=1.

But nn applies to both xvar and yvar for a 2d plot. If I've got a not-very-square area (eg Vermont) and I want square output cells, then I need to extend one set of limits far beyond reasonable limits for the data, so that the range in xvar and yvar are equal so that when divided by nn I get square cells. I can then throw away the data outside Vermont to make a map. Its a bit wasteful. If I can generate an xydf from something like

xydf = expand.grid(seq(xmin, xmax, by=step), seq(ymin, ymax, by=step))

then I get a square grid of size step x step, over a compact rectangle. This is the point where I decided it was probably easier to define the grid and get the values directly from the fitted gam object, then build a raster for plotting, rather than use visreg2D...

pbreheny commented 1 month ago

Got it, that makes sense.