9

I'm unsure how to facet by a function of the data in the data element of a ggplot object. In the following toy example, what I want to do is something like this:

df <- data.frame(x=1:8, y=runif(8), z=8:1)
ggplot(df, aes(x=x, y=y)) + geom_point() + facet_wrap( ~ (z %% 2))

But that gives the error: Error in layout_base(data, vars, drop = drop) : At least one layer must contain all variables used for facetting.

I can achieve the desired result by transforming the data frame:

ggplot(transform(df, z=z%%2), aes(x=x, y=y)) + geom_point() + facet_wrap( ~ z)

but often it's desirable to not use such a transformation, for instance if I've already been given a ggplot object and I want to add some ad-hoc faceting to it.

Ken Williams
  • 22,756
  • 10
  • 85
  • 147

1 Answers1

3

this sounds familiar to me, but I never managed to fix it - I think facet variable handling is just less powerful than aesthetic variable handling.

Addressing your root requirement - to ad-hoc facet an existing ggplot; note that you can replace wholesale the (master) data set of an existing R ggplot - for instance

myplot %+% transform(myplot$data, z=z%%2)
Alex Brown
  • 41,819
  • 10
  • 94
  • 108
  • 1
    `myplot$data$zz <- myplot$data$z%%2` may be even more straightforward. – Josh O'Brien Sep 04 '12 at 22:07
  • @Josh, true, but relies on the data set already being installed. Sometimes I build ggplots with no data and then apply multiple data sets. – Alex Brown Sep 04 '12 at 22:10
  • That's remarkably like the solution I've been using too - `myplot$data <- transform(myplot$data, z=z%%2)` . I got namespace-burned a couple times by `%+%` because some other package defined the same operator. Took me *hours* to figure that out. – Ken Williams Sep 04 '12 at 22:35