20 21
20 21

Reputation: 23

How to set background color for each panel in grouped boxplot?

I plotted a grouped boxplot and trying to change the background color for each panel. I can use panel.background function to change whole plot background. But how this can be done for individual panel? I found a similar question here. But I failed to adopt the code to my plot.

Top few lines of my input data look like

this

Code

p<-ggplot(df, aes(x=Genotype, y=Length, fill=Treatment)) +  scale_fill_manual(values=c("#69b3a2", "#CF7737"))+
geom_boxplot(width=2.5)+ theme(text = element_text(size=20),panel.spacing.x=unit(0.4, "lines"),
                             axis.title.x=element_blank(),axis.text.x=element_blank(),axis.ticks.x=element_blank(),axis.text.y = element_text(angle=90, hjust=1,colour="black")) +
labs(x = "Genotype", y = "Petal length (cm)")+
facet_grid(~divide,scales = "free", space = "free")
p+theme(panel.background = element_rect(fill = "#F6F8F9", colour = "#E7ECF1"))

Upvotes: 2

Views: 789

Answers (1)

chemdork123
chemdork123

Reputation: 13823

Unfortunately, like the other theme elements, the fill aesthetic of element_rect() cannot be mapped to data. You cannot just send a vector of colors to fill either (create your own mapping of sorts). In the end, the simplest solution probably is going to be very similar to the answer you linked to in your question... with a bit of a twist here.

I'll use mtcars as an example. Note that I'm converting some of the continuous variables in the dataset to factors so that we can create some more discrete values.

It's important to note, the rect geom is drawn before the boxplot geom, to ensure the boxplot appears on top of the rect.

ggplot(mtcars, aes(factor(carb), disp)) +
  geom_rect(
    aes(fill=factor(carb)), alpha=0.5,
    xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_boxplot() +
  facet_grid(~factor(carb), scales='free_x') +
  theme_bw()

enter image description here

All done... but not quite. Something is wrong and you might notice this if you pay attention to the boxes on the legend and the gridlines in the plot panels. It looks like the alpha value is incorrect for some facets and okay for others. What's going on here?

Well, this has to do with how geom_rect works. It's drawing a box on each plot panel, but just like the other geoms, it's mapped to the data. Even though the x and y aesthetics for the geom_rect are actually not used to draw the rectangle, they are used to indicate how many of each rectangle are drawn. This means that the number of rectangles drawn in each facet corresponds to the number of lines in the dataset which exist for that facet. If 3 observations exist, 3 rectangles are drawn. If 20 observations exist for one facet, 20 rectangles are drawn, etc.

So, the fix is to supply a dataframe that contains one observation each for every facet. We have to then make sure that we supply any and all other aesthetics (x and y here) that are included in the ggplot call, or we will get an error indicating ggplot cannot "find" that particular column. Remember, even if geom_rect doesn't use these for drawing, they are used to determine how many observations exist (and therefore how many to draw).

rect_df <- data.frame(carb=unique(mtcars$carb))  # supply one of each type of carb

# have to give something to disp
rect_df$disp <- 0

ggplot(mtcars, aes(factor(carb), disp)) +
  geom_rect(
    data=rect_df,
    aes(fill=factor(carb)), alpha=0.5,
    xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_boxplot() +
  facet_grid(~factor(carb), scales='free_x') +
  theme_bw()

enter image description here

That's better.

Upvotes: 3

Related Questions