Search code examples
rggplot2nestedfacet-wrapggh4x

Remove inner labels in ggplot with nested facets and free y-axis (facet_wrap2 - ggh4x)


I have a data frame with various categorical variables and one count variable. The variables are nested within each other. E.g. there are three trials, within each trial two groups, and both of those groups answer the same items (which can differ between the trials, but not between groups).

set.seed(32123)
test <- tibble(
  trial  = rep(c("Trial_A", "Trial_B", "Trial_C"), each = 3, times = 8),
  group  = rep(c("A", "B"), each = 36),
  result = rep(c("Fail", "Pass"), times = 36),
  item   = rep(c("item 1", "item 2", "item 3", "item 4"), each = 6, times = 3),
  tries  = round(runif(n = 72, min = 0, max = 20))) %>%
  mutate(item = case_when(item == "item 4" & group == "B" & trial == "Trial_C" ~ "item 3",
                          item == "item 3" & group == "B" & trial == "Trial_C" ~ "item 2",
                          item == "item 3" & group == "B" & trial == "Trial_A" ~ "item 2",
                          item == "item 2" & group == "B" & trial == "Trial_A" ~ "item 1",
                          TRUE ~ item))

Using ggplot2 and the facet_wrap2 function from the ggh4x package (see more about that here), I've created some nested facets showing the percentage (fail/ pass) per item/group/trial.

test %>% 
  ggplot(aes(x = item, y = tries, fill = result)) +
  geom_bar(position = "fill", stat = "identity") +
  ggh4x::facet_wrap2(dplyr::vars(trial, group),  # ggh4x package for nested facets
                     #nest_line = element_line(colour = "red"),
                     strip = strip_nested(bleed = FALSE),    # sub facets normal
                     scales = "free_y", nrow = 3, axes = "margins",
                     remove_labels = "all") +
  coord_flip() +
  theme(axis.title.x = element_blank())

The nested facets work, but I want to remove the y-axis labels of the inner facets (group B) as they are redundant and the labels in my real data are way larger. I only want to display the labels for group A. According to the help function of facet_wrap2() the argument remove_labels = "all" should "only display axis text at the outer margins", but apparently, that behaviour is ignored for axes which are set to "free" using the scales argument (which I need for the y-axis). Is there any way to overrule this behaviour within the main facets so that I can remove the y-axis labels for group B? (The same plot can also be produced with ggh4x::facet_nested_wrap() but again, no success in removing the inner labels.)

enter image description here


Solution

  • If you flip the x and y-aesthetic (making coord_flip() unnessary), you can use ggh4x::facetted_pos_scales() to explicitly remove the axis guide for the second column.

    library(ggplot2)
    library(ggh4x)
    library(tibble)
    library(dplyr)
    
    set.seed(32123)
    test <- tibble(
      trial  = rep(c("Trial_A", "Trial_B", "Trial_C"), each = 3, times = 8),
      group  = rep(c("A", "B"), each = 36),
      result = rep(c("Fail", "Pass"), times = 36),
      item   = rep(c("item 1", "item 2", "item 3", "item 4"), each = 6, times = 3),
      tries  = round(runif(n = 72, min = 0, max = 20))) %>%
      mutate(item = case_when(item == "item 4" & group == "B" & trial == "Trial_C" ~ "item 3",
                              item == "item 3" & group == "B" & trial == "Trial_C" ~ "item 2",
                              item == "item 3" & group == "B" & trial == "Trial_A" ~ "item 2",
                              item == "item 2" & group == "B" & trial == "Trial_A" ~ "item 1",
                              TRUE ~ item))
    
    ggplot(test, aes(x = tries, y = item, fill = result)) +
      geom_bar(position = "fill", stat = "identity") +
      facet_wrap2(dplyr::vars(trial, group),  # ggh4x package for nested facets
                  strip = strip_nested(),    # sub facets normal
                  scales = "free_y", nrow = 3, axes = "margins",
                  remove_labels = "all") +
      facetted_pos_scales(
        y = list(COL == 2 ~ scale_y_discrete(guide = 'none'))
      ) +
      theme(axis.title.x = element_blank())
    

    Created on 2022-08-17 by the reprex package (v2.0.1)

    Perhaps the documentation of facet_wrap2() should be clearer on when these arguments work.