Search code examples
rggplot2groupingbar-chartgeom-bar

How can I group my bars in ggplot2 by fill color, while maintaining descending order?


I am currently working on a barplot where I have data collected from timeA and timeB. I took a measurement (ex: mass) of different objects. The objects measured are not consistent in the timeA group and timeB group.

  1. I want the bars to be in descending order
  2. But I also want the bars to be grouped by time aka fill=time

How would I achieve this?

Dataset example:

df$measures <- c(2,4,26,10,18,20,14,22,12,16,24,6,8,28)
df$object <- seq.int(nrow(df)) 
df$time<- "timea"
df[6:14, 3] = "time"

This is roughly the code I have for my graph so far

plot <-ggplot(df, aes(x=reorder(object, -measures), y=measures, fill=time))+
  geom_bar(stat="identity") +
  theme_minimal()+
  theme(axis.text.x = element_text(angle = 45, hjust = 1), plot.title = element_text(hjust = 0.5))+ 
  scale_fill_manual(name="Legend", values = c("firebrick", "cornflowerblue"), labels=c("timea", "timeb")) 
plot

I attached a picture just in case of what the graph roughly looks like. Ideally, I would like all blue bars on one side in descending order and all the red bars on the other in descending order; all in the same plot.

enter image description here


Solution

  • If you want everything in the same graph you can play with factor levels in the dataframe.

    library(dplyr)
    library(ggplot2)
    
    df %>%
      arrange(time, desc(measures)) %>%
      mutate(object = factor(object, object)) %>%
      ggplot() + aes(x=object, y=measures, fill=time)+
      geom_bar(stat="identity") +
      theme_minimal()+
      theme(axis.text.x = element_text(angle = 45, hjust = 1), 
            plot.title = element_text(hjust = 0.5))+ 
      scale_fill_manual(name="Legend", values = c("firebrick", "cornflowerblue"), 
                        labels=c("timea", "timeb"))
    

    enter image description here

    You can also make use of facets here -

    ggplot(df) + aes(x=reorder(object, -measures), y=measures, fill=time)+
      geom_bar(stat="identity") +
      theme_minimal()+
      theme(axis.text.x = element_text(angle = 45, hjust = 1), 
            plot.title = element_text(hjust = 0.5))+ 
      facet_wrap(.~time, scales = 'free') + 
      scale_fill_manual(name="Legend", values = c("firebrick", "cornflowerblue"), 
                        labels=c("timea", "timeb"))
    

    enter image description here

    data

    df <- tibble::tibble(measures = c(2,4,26,10,18,20,14,22,12,16,24,6,8,28), 
          object = seq_along(measures), 
          time = sample(c("timea", "timeb"), length(measures), replace = TRUE))