Search code examples
rggplot2facet-grid

Keeping the Scale_x_discrete tick labels in ggplot after facet_grid


I am trying to add a new x tick label after facet_grid and it does not seem to work as I wished. Hopefully someone here has gone through the same and knows the trick.

To make the code reproducible I am using the mpg dataset and hopefully everyone can understand the question.

With the code below I am changing the tick axis label to the total number of cars per category:

library(tidyverse)
library(ggpubr)

p3 <- mpg %>%
  filter(class == c("compact", "subcompact")) %>%
  filter(displ == c(2,2.5)) %>%
  ggplot(aes(x=class, y=hwy, col=class))+
  geom_violin()+
  geom_point()+
  #facet_grid(cols = vars(displ))+
  stat_compare_means(method = "t.test", comparisons = list(c("compact", "subcompact")), label = after_stat("p.signf")) +  # Add statistical comparisons
  theme_bw()+
  scale_x_discrete(labels = function(x) {
    num_cars <- mpg %>%
      filter(class == c("compact", "subcompact")) %>%
      filter(displ == c(2,2.5)) %>%
      filter(class %in% x) %>%
      group_by(class) %>%
      summarise(total_cars = n())%>%
      mutate(label = total_cars)
    num_cars$label
  })
p3

This creates the following graph:

enter image description here

When I facet the graph to separate it by displ, the x axis do not work anymore although the stats are working.

p3 <- mpg %>%
  filter(class == c("compact", "subcompact")) %>%
  filter(displ == c(2,2.5)) %>%
  ggplot(aes(x=class, y=hwy, col=class))+
  geom_violin()+
  geom_point()+
  facet_grid(cols = vars(displ))+
  stat_compare_means(method = "t.test", comparisons = list(c("compact", "subcompact")), label = after_stat("p.signf")) +  # Add statistical comparisons
  theme_bw()+
  scale_x_discrete(labels = function(x) {
    num_cars <- mpg %>%
      filter(class == c("compact", "subcompact")) %>%
      filter(displ == c(2,2.5)) %>%
      filter(class %in% x) %>%
      group_by(class) %>%
      summarise(total_cars = n())%>%
      mutate(label = total_cars)
    num_cars$label
  })
p3

Makes this:

enter image description here

When I wanted the tick labels to be 2, 3, 2, 2.

Hopefully someone has an easy answer for this (I am sure it is easy).

Cheers


Solution

  • One option to set the labels individually for each panel which at the same time works when using stat_compare_means would be to use ggh4x::facetted_pos_scales which allows to set the scales (including the labels) individually per panel:

    library(ggplot2)
    library(dplyr, warn=FALSE)
    library(ggpubr)
    library(ggh4x)
    
    x_labels <- mpg %>%
      filter(class == c("compact", "subcompact")) %>%
      filter(displ == c(2, 2.5)) |> 
      count(class, displ)
    
    x_labels <- split(x_labels, x_labels$displ) |> 
      lapply(\(x) x |> select(class, n) |> tibble::deframe())
    
    mpg %>%
      filter(class == c("compact", "subcompact")) %>%
      filter(displ == c(2, 2.5)) %>%
      ggplot(aes(x = class, y = hwy, col = class)) +
      geom_violin() +
      geom_point() +
      facet_grid(cols = vars(displ), scales = "free_x") +
      stat_compare_means(method = "t.test", comparisons = list(c("compact", "subcompact")), label = after_stat("p.signf")) + # Add statistical comparisons
      theme_bw() +
      ggh4x::facetted_pos_scales(
        x = list(
          displ == 2 ~ scale_x_discrete(labels = x_labels$`2`),
          displ == 2.5 ~ scale_x_discrete(labels = x_labels$`2.5`)
        )
      )