Multirow axis labels with nested grouping variables

The strip.position argument in facet_wrap() and switch argument in facet_grid() since ggplot2 2.2.0 now makes the creation of a simple version of this plot fairly straightforward via faceting. To give the plot the uninterrupted look, set the panel.spacing to 0.

Here’s the example using the dataset with a different number of Groups per Category from @agtudy’s answer.

  • I used scales = "free_x" to drop the extra Group from the Categories that don’t have it, although this won’t always be desirable.
  • The strip.position = "bottom" argument moves the facet labels to the bottom. I removed the strip background all together with strip.background, but I could see that leaving the strip rectangle would be useful in some situations.
  • I used width = 1 to make the bars within each Category touch – they’d have spaces between them by default.

I also use strip.placement and strip.background in theme to get the strips on the bottom and remove the strip rectangle.

The code for versions of ggplot2_2.2.0 or newer:

ggplot(data = data, aes(x = Group, y = Value, fill = Group)) + 
    geom_bar(stat = "identity", width = 1) +
    geom_text(aes(label = paste(Value, "%")), vjust = -0.25) +
    facet_wrap(~Category, strip.position = "bottom", scales = "free_x") +
    theme(panel.spacing = unit(0, "lines"), 
         strip.background = element_blank(),
         strip.placement = "outside")

enter image description here

You could use space= "free_x" in facet_grid() if you wanted all the bars to be the same width regardless of how many Groups per Category. Note that this uses switch = "x" instead of strip.position. You also might want to change the label of the x axis; I wasn’t sure what it should be, maybe Category instead of Group?

ggplot(data = data, aes(x = Group, y = Value, fill = Group)) + 
    geom_bar(stat = "identity", width = 1) +
    geom_text(aes(label = paste(Value, "%")), vjust = -0.25) +
    facet_grid(~Category, switch = "x", scales = "free_x", space = "free_x") +
    theme(panel.spacing = unit(0, "lines"), 
         strip.background = element_blank(),
         strip.placement = "outside") + 
    xlab("Category")

enter image description here

Older code versions

The code for ggplot2_2.0.0, when this feature was first introduced, was a little different. I’ve saved it below for posterity:

ggplot(data = data, aes(x = Group, y = Value, fill = Group)) + 
    geom_bar(stat = "identity") +
    geom_text(aes(label = paste(Value, "%")), vjust = -0.25) +
    facet_wrap(~Category, switch = "x", scales = "free_x") +
    theme(panel.margin = unit(0, "lines"), 
         strip.background = element_blank())

Leave a Comment