18
$\begingroup$

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!

$\endgroup$
22
$\begingroup$

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:

enter image description here

| cite | improve this answer | |
$\endgroup$
  • 4
    $\begingroup$ It is a little more efficient to use the matplot function rather than looping through the columns. $\endgroup$ – Greg Snow May 29 '12 at 2:21
  • $\begingroup$ So it is (+1), I don't know why I dropped it from my mental toolkit. $\endgroup$ – jbowman May 29 '12 at 3:49
9
$\begingroup$

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:

Basis autoplot

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)
| cite | improve this answer | |
$\endgroup$

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.