rggridges

Group variable stacking when using geom_ridgeline_gradient()


I'm trying to make a ridgeline plot with a gradient using geom_ridgeline_gradient function from ggridges package. My group variable is stacking directly on top of each other rather than separating out like a normal ridgeline plot.

Ideally I want a ridgeline plot where my grouping (community) separates out from each other with the count of days with a given Air Quality Index (AQI) category colored by each AQI category's EPA assigned color.

This is what my geom_ridgeline_gradient plot looks like now:

Screenshot of how my plot looks currently

I want the site names to separate from each other to be more like a ridgeline plot like so though (https://cran.r-project.org/web/packages/ggridges/vignettes/introduction.html): Example screenshot of how I want my plot groupings to separate out

Below is some sample data with the code I used to generate my ridgeline plot (An FYI for some reason the coloring that I used to generate figure with all my data doesn't work the same for this sample data, but I'm more interested in separating out the communities than the coloring so didn't take the time to figure out that issue):

library(ggridges);library(tidyverse)

#data to generate plot
AQIcounts <- data.frame(
  site_name = rep(c("community1", "community2", "community3"),6),
  AQI_description = rep(c("Good","Moderate","Unhealthy for Sensitive Groups","Unhealthy","Very Unhealthy","Hazardous"),3),
  n = c(5472, 661, 65, 78, 30, 16, 282, 23, NA, NA, NA, NA, 3945, 441, 9, 2, NA, NA)
)

#set level ordering for AQI_description
AQIcounts$AQI_description <- factor(AQIcounts$AQI_description, levels=c("Good", "Moderate", "Unhealthy for Sensitive Groups", "Unhealthy", "Very Unhealthy", "Hazardous"))

#set color assignments to factors
palette <- c("green","yellow","orange","red","purple","maroon") #create palette
names(palette) <- levels(AQIcounts$AQI_description) #set the names of color levels
ggpalette <- scale_fill_manual(name = "AQI_description", values = palette)

ggplot(AQIcounts, aes(x=AQI_description, y = site_name, height = n, group = site_name, fill = AQI_description)) +
  geom_ridgeline_gradient()  + 
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + 
  ggpalette

Solution

  • I think the problem is with the height variable. When you set up the site_name as the y-variable, the distance between each group is 1 unit. When the height variable has values bigger than 1, the ridges will overplay each other. When the values are much bigger than one, as they are here, the result will be like you saw - all group names squeezed together.

    library(ggridges);
    library(tidyverse)
    
    #data to generate plot
    AQIcounts <- data.frame(
      site_name = rep(c("community1", "community2", "community3"),each=6),
      AQI_description = rep(c("Good","Moderate","Unhealthy for Sensitive Groups","Unhealthy","Very Unhealthy","Hazardous"),3),
      n = c(5472, 661, 65, 78, 30, 16, 282, 23, 0, 0, 0, 0, 3945, 441, 9, 2, 0, 0)
    )
    
    #set level ordering for AQI_description
    AQIcounts$AQI_description <- factor(AQIcounts$AQI_description, levels=c("Good", "Moderate", "Unhealthy for Sensitive Groups", "Unhealthy", "Very Unhealthy", "Hazardous"))
    
    #set color assignments to factors
    palette <- c("green","yellow","orange","red","purple","maroon") #create palette
    names(palette) <- levels(AQIcounts$AQI_description) #set the names of color levels
    ggpalette <- scale_fill_manual(name = "AQI_description", values = palette)
    ggplot(AQIcounts, 
           aes(x= AQI_description, 
               y = site_name, 
               height = n, 
               group = site_name,
               fill = AQI_description)) +
      geom_ridgeline_gradient(scale=.9)  + 
      theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + 
      ggpalette
    

    You could change this by normalizing the counts to have a maximum value of 1. I did this below simply by replacing n with n/max(n).

    ggplot(AQIcounts %>% mutate(n = n/max(n)), 
           aes(x= AQI_description, 
               y = site_name, 
               height = n, 
               group = site_name,
               fill = AQI_description)) +
      geom_ridgeline_gradient(scale=.9)  + 
      theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + 
      ggpalette
    

    If you didn't care about the relative differences across groups (though I suspect you do), you could do the normalization by groups. Again, this eliminates the baseline differences between groups, but might show whether the patterns across the groups are similar.

    ggplot(AQIcounts %>%
             group_by(site_name) %>% 
             mutate(n = n/max(n)), 
           aes(x= AQI_description, 
               y = site_name, 
               height = n, 
               group = site_name,
               fill = AQI_description)) +
      geom_ridgeline_gradient(scale=.9)  + 
      theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + 
      ggpalette
    

    Created on 2025-02-11 with reprex v2.1.1.9000