I am using "smooth.spline" in R. Here is a snippet from the documentation:


smooth.spline {stats} R Documentation

Fit a Smoothing Spline Description Fits a cubic smoothing spline to the supplied data.

Usage smooth.spline(x, y = NULL, w = NULL, df, spar = NULL, cv = FALSE, all.knots = FALSE, nknots = NULL, keep.data = TRUE, df.offset = 0, penalty = 1, control.spar = list(), tol = 1e-6 * IQR(x))

My question is that:

I have two vectors of data x and y, where the lower bound for x is -100 and the upper bound for x is +100.

And I knew that for y=f(x):



That's to say, I would like to have the lower boundary and upper boundary points to be forced passing thru by the cubic spline procedure.

Because these two points are accurate and precise.

How to do that?

Could anybody please help me?

Thanks a lot!

  • $\begingroup$ Have you tried adjusting the weights vector (w) to achieve this? $\endgroup$ – whuber May 29 '12 at 16:40
  • $\begingroup$ what should be a good weighting scheme? I guess I was asking methods to make sure that the two "absolutely precise" points should be forced to be passed with no residual errors at all... $\endgroup$ – Luna May 29 '12 at 17:48
  • $\begingroup$ I've added the following weights... the results seem to be no change than before...: w=rep(1, length(x)) w[1]=1000 q=smooth.spline(x=x, y=y, cv=T) $\endgroup$ – Luna May 29 '12 at 17:53
  • 1
    $\begingroup$ That approach works for me with random data, Luna. Perhaps you should post an example. $\endgroup$ – whuber May 29 '12 at 17:56
  • 1
    $\begingroup$ Perhaps try w[x==100] <- 1000 and w[x==-100] <- 1000 to make sure you're catching all the endpoints in the data. $\endgroup$ – jbowman May 29 '12 at 18:08

Rather than use smooth.spline() in the stats package, there is a function cobs() in the cobs package that allows you to do exactly the sort of thing you want. COBS stands for Constrained B-splines. Possible constraints include going through specific points, setting derivatives to specified values, monotonicity (increasing or decreasing), concavity, convexity, periodicity, etc.

In your case, use

cobs(x, y, pointwise=rbind(c(0,-100,-1),c(0,100,1)))

I cannot think of any way to do it using smooth.spline. If you were to use a spline basis such as bs from the splines package, then you could possibly do this using quadradic programming to constrain the endpoints, but it could be complicated figuring out the constraints.

Here is an approach that uses xsplines (different but similar to other types of splines) and the optim function to find the values to use (nls could be used as well). I chose 3 internal equally spaced control points and a shape of 1, but you could play with these to compare the fit:

x <- seq( -100, 100, length=101 )
y <- sin( x/200*pi ) + rnorm(101, 0, 0.15)

myfun <- function(par) {
    yh <- c(-1, par, 1)
    xh <- c(-100, -50, 0, 50, 100)
    sp <- xspline( xh,yh, shape=1, draw=FALSE)
    yhat <- approx( sp, xout=x )$y
    sum( (y-yhat)^2 )

out <- optim( c(-.5, 0, .5), myfun )

xspline( c(-100, -50, 0, 50, 100), c(-1, out$par, 1), shape=1,
        border='blue' )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.