Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add secondary headings to facet_wraps

Tags:

r

ggplot2

I have a data frame consisting of eight sites (i.e., A,B,C...H) spread across two locations (i.e., North and South). I have made a figure for each site using facet_wrap() however, I would like to add an additional column heading denoting the site's location. How can I do this?

Example Data

library(ggplot2)
library(dplyr)

set.seed(123)

df <- data.frame(matrix(ncol = 4, nrow = 24))
colnames(df)[1:4] <- c('location','site','x','y')
df$location <- rep(c('North','North','North','South','South','South'),4)
df$site <- c('A','A','A','E','E','E','B','B','B','F','F','F',
             'C','C','C','G','G','G','D','D','D','H','H','H')
df$x <- rep(seq(0,12,4),6)
df$y <- rnorm(24,50,20)
df

Example Figure (missing the secondary header)

df %>%
  mutate(across(site, factor, levels = c('A','B','E','F',
                                         'C','D','G','H'))) %>%
  ggplot(aes(x = x, y = y)) +
  geom_point() +
  geom_line() +
  scale_x_continuous(breaks = seq(0,12,3),
                     limits = c(0,12)) +
  scale_y_continuous(breaks = seq(0,max(df$y),5)) +
  theme_bw() +
  facet_wrap(~site, nrow = 2)

Here is a similar SO question (link here) however, I could not get it to work when there is already a scale_x_continuous() function called and it was not clear how that answer would work with multiple headings on the same axis.

Here is an example of the output I am looking for. Note the df$location is the secondary x-axis header and that the left two columns are North sites while the right two columns are South sites. enter image description here

like image 981
tassones Avatar asked Sep 19 '25 07:09

tassones


1 Answers

Building on akrun's answer, you can hide a strip by setting the corresponding elements to blank in strip_nested(). I haven't figured out a way to remove the redundant space though.

library(ggh4x)
#> Loading required package: ggplot2
library(ggplot2)
library(dplyr)


set.seed(123)

df <- data.frame(matrix(ncol = 4, nrow = 24))
colnames(df)[1:4] <- c('location','site','x','y')
df$location <- rep(c('North','North','North','South','South','South'),4)
df$site <- c('A','A','A','E','E','E','B','B','B','F','F','F',
             'C','C','C','G','G','G','D','D','D','H','H','H')
df$x <- rep(seq(0,12,4),6)
df$y <- rnorm(24,50,20)
df %>%
  mutate(across(site, factor, levels = c('A','B','E','F',
                                         'C','D','G','H'))) %>%
  ggplot(aes(x = x, y = y)) +
  geom_point() +
  geom_line() +
  scale_x_continuous(breaks = seq(0,12,3),
                     limits = c(0,12)) +
  scale_y_continuous(breaks = seq(0,max(df$y),5)) +
  theme_bw() +
  facet_manual(
    vars(location, site), design = "ABEF\nCDGH",
    strip = strip_nested(
      text_x = list(element_text(), element_blank())[c(1,1,2,2,rep(1, 8))],
      background_x = list(element_rect(), element_blank())[c(1,1,2,2,rep(1, 8))]
    ))

Created on 2023-01-05 by the reprex package (v2.0.1)

like image 175
teunbrand Avatar answered Sep 21 '25 22:09

teunbrand