Ggplot: How to remove axis labels on selected facets only?

Basically, I'm looking for a way to remove x-axis label in some given facets.
In this case, remove the x.axis labels every other facet. I searched around but didn't find any viable solution. Thanks!

Desired output

Sample data and code


library(tidyverse)

dat <- structure(list(Year = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
          2L, 3L, 3L, 3L, 3L), .Label = c("2001", "2002", "2003"), class = "factor"), 
          Company = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 
          2L, 3L, 4L), .Label = c("AAA", "BBB", "CCC", "DDD"), class = "factor"), 
          Rank = c(1, 3, 2, 4, 5, 4, 2, 3, 2, 3, 5, 1), Rank_rev = c(5, 
          3, 4, 2, 1, 2, 4, 3, 4, 3, 1, 5)), 
          class = c("data.frame"), row.names = c(NA, -12L))

dat <- dat %>% 
  mutate(Company = factor(Company),
         Year = factor(Year),
         Rank_rev = max(Rank) - Rank + 1)

myplot <- ggplot(dat, aes(x = Year, y = Rank_rev)) +
  facet_grid(.~ Company) +
  geom_col(aes(fill = Company)) +
  geom_text(
    aes(x = Year, y = Rank_rev,
        label = Rank),
    nudge_y = 0.25,
    size = 5,
    hjust = 0.5,
    color = "black") +
  scale_fill_brewer(palette = "Set2") +
  scale_x_discrete(expand = c(0, 0)) +
  scale_y_continuous(expand = expand_scale(mult = c(0, 0.1))) +
  theme_minimal() +
  theme(axis.text.y = element_blank())
myplot

One way to do this is to replace the year values with empty strings of progressively increasing length, and then set space="free_x" and scales="free_x" in facet_grid. You could just hard-code this for your example, but you could also try to make it more general to deal with arbitrary numbers of companies and years, as in the code below.

First we use as.numeric to convert Company into its numeric factor codes and use these as a grouping variable. Then, when this code is odd (as tested by company.numeric %% 2 == 1), we replace the Year values with a sequence of blank strings (if Year isn't already sorted, it needs to be sorted before doing this).

# For every other Company, replace Year with a sequence of blank strings
dat.update = dat %>% 
  group_by(company.numeric = as.numeric(Company)) %>% 
  mutate(Year = case_when(company.numeric %% 2 == 1 ~ map_chr(1:n(), ~ paste(rep(" ", .x), collapse="")),
                           TRUE ~ as.character(Year))) 

myplot <- ggplot(dat.update, aes(x = Year, y = Rank_rev)) +
  facet_grid(.~ Company, scales="free_x", space="free_x")  +  
  ... # (rest of plot code is unchanged)

myplot

Rplot

7 Likes

Another option would be to tag each year you want to remove and then supply a function to scale_x_discrete to suppress those years.

# add 'no_display' to years we don't want labeled
dat.update <- dat %>%
  mutate(Year = if_else(as.numeric(Company) %% 2 == 0,
                              as.character(Year), 
                              paste0(as.character(Year), 'no_display')))

# function to suppress labels
delete_no_display <- function(v) {
  if_else(str_detect(v, 'no_display'), '', v)
}

# changes to plot command
myplot <- ggplot(dat.update, aes(x = Year, y = Rank_rev)) +
  facet_grid(. ~ Company, scale = 'free_x') +
...
  scale_x_discrete(expand = c(0,0), label = delete_no_display) +
...
8 Likes

Thank you @joels & @Galangjs ! Appreciate it!

1 Like