Visualizing a spline basis

Textbooks typically have nice example plots of of the basis for uniform splines when they're explaining the topic. Something like a row of little triangles for a linear spline, or a row of little humps for a cubic spline.

This is a typical example:

http://support.sas.com/documentation/cdl/en/statug/63033/HTML/default/viewer.htm#statug_introcom_a0000000525.htm

I'm wondering if there is an easy way to generate a plot of the spline basis using standard R functions (like bs or ns). I guess there's some simple piece of matrix arithmetic combined with a trivial R program which will spit out a pretty plots of a spline basis in an elegant way. I just can't think of it!

Try this, as an example for B-splines:

x <- seq(0, 1, by=0.001)
spl <- bs(x,df=6)
plot(spl[,1]~x, ylim=c(0,max(spl)), type='l', lwd=2, col=1,
xlab="Cubic B-spline basis", ylab="")
for (j in 2:ncol(spl)) lines(spl[,j]~x, lwd=2, col=j)


Giving this:

• It is a little more efficient to use the matplot function rather than looping through the columns. May 29 '12 at 2:21
• So it is (+1), I don't know why I dropped it from my mental toolkit. May 29 '12 at 3:49

Here's an autoplot method for the "basis" class (which both bs and ns inherit from):

library(ggplot2)
library(magrittr)
library(reshape2)
library(stringr)
autoplot.basis <- function(basis, n=1000) {
all.knots <- sort(c(attr(basis,"Boundary.knots") ,attr(basis, "knots"))) %>%
unname
bounds <- range(all.knots)
knot.values <- predict(basis, all.knots) %>%
set_colnames(str_c("S", seq_len(ncol(.))))
newx <- seq(bounds[1], bounds[2], length.out = n+1)
interp.values <- predict(basis, newx) %>%
set_colnames(str_c("S", seq_len(ncol(.))))
knot.df <- data.frame(x=all.knots, knot.values) %>%
melt(id.vars="x", variable.name="Spline", value.name="y")
interp.df <- data.frame(x=newx, interp.values) %>%
melt(id.vars="x", variable.name="Spline", value.name="y")
ggplot(interp.df) +
aes(x=x, y=y, color=Spline, group=Spline) +
geom_line() +
geom_point(data=knot.df) +
scale_color_discrete(guide=FALSE)
}


This lets you just call autoplot on an ns or bs object. Taking jbowman's example:

library(splines)
x <- seq(0, 1, by=0.001)
spl <- bs(x,df=6)
autoplot(spl)


which produces:

Edit: This will be included in the next version of the ggfortify package: https://github.com/sinhrks/ggfortify/pull/129. After that, I believe all you should need is:

library(splines)
library(ggfortify)
x <- seq(0, 1, by=0.001)
spl <- bs(x,df=6)
autoplot(spl)