I learned yesterday that creating fill textures in bar charts in ggplot is not easy. Yes, there is a clever hack (posted here on SO), but it takes a lot of coding. Why does this matter? Well, yesterday, I wanted to create a bar chart that conveyed three pieces of information: (1) the number of times predictions from a paper had been tested in the literature, (2) the type or category of each prediction (“Category”), and (3) the way in which each prediction had been dealt with in the paper (e.g., accepted as fact vs. tested empirically; “Recognition”). (Here is a bit of background about the project). And, I wanted to use code that I could interpret a few months down the line.
To begin, I created a multi-panel plot (Figure 1) using the facet_wrap() option in ggplot. This figure is fine (and perhaps clearer than the final result), but my co-authors challenged me to condense this information into a single plot. I envisioned a stacked bar chart. As in Figure 1, "Category" would dictate the color of each bar. Then, each bar would have an overlain fill text (like this) depending on the variable “Recognition.” This is when I discovered that creating fill textures in ggplot is not easy.
My solution? Shading! In ggplot, “alpha” can be set as an aesthetic – therefore, its value can be controlled by a variable (in my case, “Recognition”). And, just as you can control the aesthetic parameters of fill colors, outlines, etc, in your plot, so can you control the aesthetic parameters of your shading. The final result is below (Fig. 2).
Here is the code for the graph:
plot.2 <- ggplot(newdata, aes(x=factor(pred.no), y=value)) +
geom_bar(stat="identity", aes(fill=type)) + # Sets information for variable 1: "Category"
breaks=c("Community Energetics", "Community Structure", "Life History", "Nutrient Cycling", "Selection Pressure", "Overall Homeostasis")) + # Order of "Category" in legend
geom_bar(stat="identity", fill="black", aes(alpha=variable)) + # Sets information for variable 2: "Recognition"
breaks=c("mention", "as_fact", "data_notest", "test"), # can use to set order
labels=c("Mention", "As Fact", "Data w/o Test", "Test")) +
scale_y_continuous(expand = c(0,0)) + # Bars flush with x-axis
xlab("Prediction #") +
plot.2 + theme(legend.key=element_rect(color="#EEEEEE")) # Light grey box around legend keys