Hello Simon,

thanks for your response!

I incorporated the intercept, i.e. coef(my_gam)[1] into the spline. That is, my B-spline coefficients are the intercept for the first one, and for all others I added the intercept to them (see the code below if I'm not clear)

Now I *almost* reproduce the spline:

http://i.imgur.com/pDZuHev.png

The red line is what plot(gam) does, the black line is my manual reproduction.
Could you hint me towards where my mistake is?

Best wishes,
 Alex

New code:

my_gam <- gam(y~s(x, bs="ps", m=m, k=length(myknots)-m-2), knots=list(x=myknots))

intercept <- coef(my_gam)[1]
coefs <- rep(NA, length(coef(my_gam)))
coefs[1]  <- intercept
coefs[-1] <- intercept + coef(my_gam)[-1]

spline_y <- construct_bspline(x, my_gam$smooth[[1]]$knots, coefs, m)

plot(my_gam, lwd=2, col="red")
lines(x,spline_y - mean(spline_y)) # subtract mean(spline_y) to have it centered around 0


On 06/18/2014 11:03 AM, Simon Wood wrote:
mgcv:gam automatically imposes sum-to-zero constraints on the smooths in
a model (even if there is only one smooth). This is to avoid lack of
identifiability with the intercept. The constraint removes one
coefficient and shifts the curve...

best,
Simon

On 17/06/14 15:40, Alexander Engelhardt wrote:
Hello R-helpers,

I am working through Simon Wood's GAM book and want to specify my own
knot locations (on even tens, i.e. 10, 20, 30, etc.). Then, I want to
compute a GAM on that area, and given the coefficients, reconstruct the
same P-spline that is drawn in plot(my_gam).

I'm failing.
Here is what I am doing. I think the two plot calls at the end should
produce the same line, but they don't:


bspline <- function(x,k,i,m=2){
     ## "draws" one B-spline basis function
     ## order of splines is m+1, i.e. m=2 means cubic splines of order 3
     if(m==-1){
         res <- as.numeric(x<k[i+1] & x>=k[i])
     } else {
         z0 <- (x-k[i]) / (k[i+m+1]-k[i])
         z1 <- (k[i+m+2]-x)/(k[i+m+2]-k[i+1])
         res <- z0*bspline(x,k,i,m-1) + z1*bspline(x,k,i+1,m-1)
     }
     res
}

construct_bspline <- function(x, knots, coefs, m){
     ## Constructs a complete spline from a set of knots and coefficients
     y <- rep(0, times=length(x))
     for(i in seq(coefs)){
         coef <- coefs[i]
         y <- y + coefs[i] * bspline(x, knots, i, m)
     }
     y
}

span_knots <- function(start, end, h, m){
     ## create knots of distance 'h' from 'start' to 'end',
     ##  to use with B-splines of order m+1
     first_knot <- start - start%%h - (m+1)*h
     last_knot <- end-1 + (h - (end-1)%%h) + (m+1)*h

     knots <- seq(first_knot, last_knot, by=h)
     knots
}

## create data:
x <- 125:197
y <- cos(sqrt(40*x)/3) + 3  # mean=3, s(0)=4
plot(x,y)

m <- 2  # use cubic splines of order m+1=3

myknots <- span_knots(start=min(x), end=max(x), h=10, m=m)

## Why do I have to set 'k' to length(myknots)-m-2 here? According to
the book, it should be length(myknots)-m-1.
my_gam <- gam(y~s(x, bs="ps", m=m, k=length(myknots)-m-2),
knots=list(x=myknots))

## Here, I construct my own spline with the coefficients of the GAM,
except coef()[1] which is the intercept
spline_y <- construct_bspline(x, my_gam$smooth[[1]]$knots,
coef(my_gam)[-1], mm)

plot(my_gam)
lines(x,spline_y)  # why is this different? It seems shifted on the x-
and y-axis

______________________________________________
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.



______________________________________________
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.

Reply via email to