Search code examples
rggplot2axis-labels

How to create a ggplot in R that has multilevel labels on the y axis and only one x axis


I am trying to create a tile plot with ggplot in R with a multilevel label on the Y axis, and with only one copy of the x axis (e.g. no facets). The desired outcome is something like this (just imagine that the tiles are all there): enter image description here

Here is what I have so far:

dat<- as.data.frame(cbind(Species = rep(c("a", "b", "c", "d", "e", "f", "g"),each = 3 ), 
                            threats = rep(c("1", "2", "3"), 7),
                            elev_grp = c(rep("Low", 9), rep("Mid", 9), rep("High", 3)), 
                            match = sample(1:3, size = 21, replace = T)))
dat$match.labs<- ifelse(dat$match == 1, "Both",
                        ifelse(dat$match == 2, "Neither", "One"))

ggplot(dat, aes(reorder(threats, match), Species, fill = match.labs))+
  geom_tile()+
  scale_fill_manual(values = c("#bd421f",
                               "#3fadaf",
                               "#ffb030"))

That gives me this: enter image description here

Faceting is inappropriate because every species has a "match" value for every level of "threats", and there are dozens of levels in my actual dataset, which makes repeating the x-axis over different facets of "elev_grp" impractical. I'd also considered stacked facets, but couldn't figure out how to force them to share one x axis so there aren't huge grey areas in the plot...

Any help would be appreciated. Thanks for your time!


Solution

  • You can do the old "facet that doesn't look like a facet" trick:

    dat$elev_grp <- factor(dat$elev_grp, c("High", "Mid", "Low"))
    
    ggplot(dat, aes(reorder(threats, match), Species, fill = match.labs))+
      geom_tile()+
      scale_fill_manual(values = c("#bd421f",
                                   "#3fadaf",
                                   "#ffb030")) +
      scale_y_discrete(drop = TRUE, expand = c(0, 0)) +
      facet_grid(elev_grp~., scales = "free", space = "free_y", switch = "y") +
      theme(strip.placement = "outside",
            panel.spacing = unit(0, "in"),
            strip.background.y = element_rect(fill = "white", color = "gray75"))
    

    enter image description here