8

Is it possible to have more than one background color for the plot area (but not the panel area) on a ggplot2 graph? A hunch tells me that it might be possible to do that as some sort of background color for axes.

This is what my current chart looks like:

And this is what I would like to achieve:

[The final colours will certainly be different. I just used this example in its simplest form in order to ease the discussion]

I tried passing "fill" arguments to:

theme(axis.text.y = element_text(fill = "red"),

but it obviously failed as that argument is meant for element_rect.

Stedy
  • 7,359
  • 14
  • 57
  • 77
Fael
  • 183
  • 2
  • 10
  • 1
    I suppose there is no native way to do that. As far as I can tell, the plot consists of three main rectangle areas: entire plot (plot.background), plotting area (panel.background) and legend area (legend.background). The only opportunity I see is either modifying the source (rather desperate move), or additionally push another layer with geom_rect. I have no idea how to do that, though. The closest concept I could find is http://stackoverflow.com/questions/10525957/how-to-draw-lines-outside-of-plot-area-in-ggplot2?rq=1 – tonytonov Dec 26 '13 at 12:36

1 Answers1

7

You can add grobs in the margins - i had to mess about with the annotation ranges to get it to fit - so expect there is a more robust method. Adapted from this question: How to place grobs with annotation_custom() at precise areas of the plot region?

library(grid)

data(mtcars)
#summary(mtcars)

myGrob <- grobTree(rectGrob(gp=gpar(fill="red", alpha=0.5)),
               gTree(x0=0, x1=1, y0=0, y1=1, default.units="npc"))

myGrob2 <- grobTree(rectGrob(gp=gpar(fill="yellow", alpha=0.5)),
               gTree(x0=0, x1=1, y0=0, y1=1, default.units="npc"))

p <- ggplot(mtcars , aes(wt , mpg)) + 
 geom_line() +
 scale_y_continuous(expand=c(0,0)) + 
 scale_x_continuous(expand=c(0,0)) + 
 theme(plot.margin=unit(c(1, 1, 1,1), "cm")) +
 annotation_custom(myGrob, xmin=-0.5, xmax=1.5, ymin=7.4, ymax=33.9 ) +
 annotation_custom(myGrob2, xmin=1.5, xmax=5.4, ymin=7.4, ymax=10.4 )

g <- ggplotGrob(p)
g$layout$clip[g$layout$name=="panel"] <- "off"
grid.draw(g)

enter image description here

Community
  • 1
  • 1
user20650
  • 24,654
  • 5
  • 56
  • 91
  • This is exactly what I was looking for. Thank you very much. I would like to add though that your arguments for annotation_custom seem to be hard-coded and that could pose a problem when automating these graphs. I think it would be more effective to have them as functions of the data like this: annotation_custom(myGrob2, xmin=min(mtcars$wt), xmax=Inf, ymin=-max(mtcars$mpg), ymax=min(mtcars$mpg)) + annotation_custom(myGrob, xmin=-Inf, xmax=min(mtcars$wt), ymin=-max(mtcars$mpg), ymax=Inf). For some reason, -Inf works on the horizontal axis but not on the vertical one. – Fael Dec 26 '13 at 18:38
  • @Fael, see [this answer](http://stackoverflow.com/questions/17492230/how-to-place-grobs-with-annotation-custom-at-precise-areas-of-the-plot-region/17493256#17493256) for ideas on how to avoid hard-coding of positions of grobs. – Henrik Dec 26 '13 at 22:28