R: Fit custom n-th degree polynomial to each facet in facet_wrap'd ggplot

Viewed 183

I'm trying to fit a unique nth-degree polynomial fit to each facet in a facet-wrapped ggplot, but can't quite seem to get this to work.

One can use a uniform 1st degree linear fit for all facets with the following:

library(ggplot2)

df <- diamonds

polys <- c(2, 2, 2, 2, 2)

custom.smooth <- function(formula, data,...) {
  smooth.call <- match.call()
  smooth.call[[1]] <- lm
  eval.parent(smooth.call)
}

ggplot(df, aes(x=carat, y=price)) +
  geom_point(alpha=0.1) +
  facet_wrap(~cut, scales='free') +
  stat_smooth(method='custom.smooth')

What I can't figure out is how to use the ith integer in polys as the polynomial degree for the ith facet in the plot.

Does anyone know how to achieve this behavior? Any help others can offer would be greatly appreciated!

1 Answers

You can split the data to produce a separate smooth for each facet.

# set up
library(ggplot2)

df <- diamonds
custom.smooth <- function(formula, data,...) {
  smooth.call <- match.call()
  smooth.call[[1]] <- lm
  eval.parent(smooth.call)
}

Run function

ggplot(df, aes(x=carat, y=price)) +
  geom_point(alpha=0.1) +
  facet_wrap(~cut, scales='free') +
  mapply(function(dat, i) 
         stat_smooth(data=dat, method='custom.smooth', formula=y~poly(x, i)),
         dat=split(df, df$cut), i=1:length(unique(df$cut)))

To produce

enter image description here


mapply takes a function to apply over multiple arguments. First a function is defined that takes two arguments: 1) data, 2) the polynomial degree. This is no different from defining any other function

function(dat, i) stat_smooth(data=dat, 
                             method='custom.smooth', 
                             formula=y~poly(x, i))  

The arguments are then defined data: the raw data is partitioned into the data that is used in each facet, and a vector of degrees, 1 to 5, is defined (this could be your polys vector)

split(df, df$cut)
1:length(unique(df$cut))

These arguments are then passed to mapply, via the dots argument, which runs the function over each set of parameters, to produce a named list of smooths that automagically are added to the facets.

Related