Search code examples
rggplot2facet

How can I show different degree polynomial fits in ggplot2 with facet_grid?


I want to use facets (because I like the way they look for this) to show polynomial fits of increasing degree. It's easy enough to plot them separately as follows:

df <- data.frame(x=rep(1:10,each=10),y=rnorm(100))

ggplot(df,aes(x=x,y=y)) + stat_smooth(method="lm",formula=y~poly(x,2))
ggplot(df,aes(x=x,y=y)) + stat_smooth(method="lm",formula=y~poly(x,3))
ggplot(df,aes(x=x,y=y)) + stat_smooth(method="lm",formula=y~poly(x,4))

I know I can always combine them in some fashion using grobs, but I would like to combine them using facet_grid if possible. Maybe something similar to:

poly2 <- df
poly2$degree <- 2
poly3 <- df
poly3$degree <- 3
poly4 <- df
poly4$degree <- 4
polyn <- rbind(poly2,poly3,poly4)

ggplot(polyn,aes(x=x,y=y)) + stat_smooth(method="lm",formula=y~poly(x,degree)) +
  facet_grid(degree~.)

This doesn't work, of course, because the faceting does not work on y~poly(x,degree) so that degree gets pulled from the data. Is there some way to make this work?


Solution

  • You can always predict the points manually and then facet quite easily,

    ## Data
    set.seed(0)
    df <- data.frame(x=rep(1:10,each=10),y=rnorm(100))
    
    ## Get poly fits
    dat <- do.call(rbind, lapply(1:4, function(d)
        data.frame(x=(x=runif(1000,0,10)),
                   y=predict(lm(y ~ poly(x, d), data=df), newdata=data.frame(x=x)),
                   degree=d)))
    
    ggplot(dat, aes(x, y)) +
      geom_point(data=df, aes(x, y), alpha=0.3) +
      geom_line(color="steelblue", lwd=1.1) +
      facet_grid(~ degree)
    

    enter image description here

    To add confidence bands, you can use the option interval='confidence' with predict. You might also be interested in the function ggplot2::fortify to get more fit statistics.

    dat <- do.call(rbind, lapply(1:4, function(d) {
        x <- seq(0, 10, len=100)
        preds <- predict(lm(y ~ poly(x, d), data=df), newdata=data.frame(x=x), interval="confidence")
        data.frame(cbind(preds, x=x, degree=d))
    }))
    
    ggplot(dat, aes(x, fit)) +
      geom_point(data=df, aes(x, y), alpha=0.3) +
      geom_line(color="steelblue", lwd=1.1) +
      geom_ribbon(aes(x=x, ymin=lwr, ymax=upr), alpha=0.3) +
      facet_grid(~ degree)
    

    enter image description here