44

I'm using the "tips" data set in ggplot2. If I do

sp = ggplot(tips,aes(x=total_bill, y = tip/total_bill)) + 
        geom_point(shape=1) + 
        facet_grid(sex ~ day)

The plot comes out fine. But I now want to change the panel background for just the plots under "Fri". Is there a way to do this?

Even better, can I conditionally change colors by passing parameters? For example if more than 3 points are below 0.1, then change panel background (for just that panel) to a certain color while all others remain the default light grey?

2 Answers 2

87

The general rule for doing anything in ggplot2 is to,

  1. Create a data frame that encodes the information you want to plot
  2. Pass that data frame to a geom

This is made a bit more complicated in this case because of the particular aspect of the plot you want to alter. The Powers That Be designed ggplot2 in a way that separates data elements of the plot (i.e. geom's) from non-data elements (i.e. theme's), and it so happens that the plot background falls under the "non-data" category.

There is always the option of modifying the underlying grid object manually but this is tedious and the details may change with different versions of ggplot2. Instead, we'll employ the "hack" that Hadley refers to in this question.

#Create a data frame with the faceting variables
# and some dummy data (that will be overwritten)
tp <- unique(tips[,c('sex','day')])
tp$total_bill <- tp$tip <- 1

#Just Fri
ggplot(tips,aes(x=total_bill, y = tip/total_bill)) + 
        geom_rect(data = subset(tp,day == 'Fri'),aes(fill = day),xmin = -Inf,xmax = Inf,
            ymin = -Inf,ymax = Inf,alpha = 0.3) +
        geom_point(shape=1) + 
        facet_grid(sex ~ day) 

enter image description here

#Each panel
ggplot(tips,aes(x=total_bill, y = tip/total_bill)) + 
        geom_rect(data = tp,aes(fill = day),xmin = -Inf,xmax = Inf,
            ymin = -Inf,ymax = Inf,alpha = 0.3) +
        geom_point(shape=1) + 
        facet_grid(sex ~ day) 

enter image description here

9
  • Thanks much for the help. Definitely useful.
    – broccoli
    Commented Mar 24, 2012 at 0:33
  • 3
    Note that setting panel.background and the above geom_rect behave differently when behind geom_raster because an optimization can take place when there is "nothing" behind the raster. When saved as a pdf, the geom_rect version is a significantly larger file and virtually unopenable with most pdf viewers!
    – momeara
    Commented Jun 27, 2013 at 1:53
  • Is it possible to do this with a continuous feature and scale? Commented Sep 2, 2015 at 17:52
  • 1
    Great solution, but does not work well if you have fill aesthetic in other layers, like geom_bar.
    – yuk
    Commented Apr 10, 2021 at 22:32
  • 1
    Is there any way to pick specific colors for the days? I have tried adding a column with color names "red", "blue", "green" etc. ggplot seems to use them but not in the order I specified.
    – ktm
    Commented Feb 1, 2023 at 19:46
3

I cannot comment yet.. so here is an additional answer to joran his answer.

If you are having trouble with the transparency setting, like setting alpha = 0.2 but not noticing any difference, it might be because of the data that you give to ggplot.

"Thanks for clarifying your question. This was puzzling to me, so I went to google, and ended up learning something new (after working around some vagaries in their examples). Apparently what you are doing is drawing many rectangles on top of each other, effectively nullifying the semi-transparency you want. So, the only ways to overcome this are to hard-code the rectangle coordinates in a separate df"

This answer comes from geom_rect and alpha - does this work with hard coded values?

Not the answer you're looking for? Browse other questions tagged or ask your own question.