Search code examples
rplotspline

How to generate B-spline of degree zero using R


I am currently working with B-splines using R's function bs from the package splines and as a graphic example I would like to provide a figure showing the differences between set of splines with different degrees.

The problem is that bs only supports degrees bigger than 0. A spline of degree zero, is nothing more than an indicator function for the given region defined by the knots, but I don't really know how to generate it. This is what I've done so far

x<-seq(0,1,length.out =1000)
    par(mfrow=c(3,1))
    B1<-bs(x,knots = seq(0,1,length.out = 11)[-c(1,11)],Boundary.knots = c(0,1),intercept = T,degree = 1)
    matplot(x,B1,type="l",lty=1,ylim = c(-0.1,1.2),xlab = "",ylab = "")
    abline(v=seq(0,1,length.out = 11),lty=2)
    legend("top", legend ="B-splines of order 2")

    B2<-bs(x,knots = seq(0,1,length.out = 11)[-c(1,11)],Boundary.knots = c(0,1),intercept = T,degree = 2)
    matplot(x,B2,type="l",lty=1,ylim = c(-0.1,1.2),xlab = "",ylab = "")
    abline(v=seq(0,1,length.out = 11),lty=2)
    legend("top", legend ="B-splines of order 3")

    B3<-bs(x,knots = seq(0,1,length.out = 11)[-c(1,11)],Boundary.knots = c(0,1),intercept = T,degree = 3)
    matplot(x,B3,type="l",lty=1,ylim = c(-0.1,1.2),xlab = "",ylab = "")
    abline(v=seq(0,1,length.out = 11),lty=2)
    legend("top", legend ="B-splines of order 4")

This image taken from Hastie et.al (2017) is basically what I am missing. enter image description here

Thanks in advance


Solution

  • As I understand from the comments, you want a function that given an input vector x of n points returns a series of n-1 "splines"; where the ith spline is defined as having the value 1 in the range x[i] < x < x[i+1] or 0 elsewhere.

    We can do this so:

    x <- seq(0,1,length.out =10)
    
    zero_spline = function(x, xout, n=1000) {
      if (missing(xout)) xout = seq(min(x), max(x), length.out = n)
      zs = data.frame()
      y = numeric(length(xout))
      for (i in 1:(length(x)-1L)) {
        yi = y
        yi[(xout > x[i]) & (xout < x[i+1])] = 1
        zs = rbind(zs, data.frame(xout, yi, interval=i))
      }
      zs
    }
    
    zs = zero_spline(x, n=100) 
    
    library(ggplot2)
    ggplot(zs, aes(xout, yi, color=factor(interval))) +
      geom_line()
    

    enter image description here