Search code examples
rggplot2geom-bar

Sort a bar plot based on two conditions in ggplot


I would like to create a bar plot that is arranged into groups and within those groups, sorted from the *minimum to maximum value.

To recreate the example I will use the following data frame

df <- data.frame(
  stringsAsFactors = FALSE,
             Sites = c("Site 1","Site 2","Site 3",
                       "Site 4","Site 5","Site 6","Site 7","Site 8","Site 9",
                       "Site 10","Site 11"),
            Values = c(184.7955548,171.1466314,
                       245.5952181,188.3072784,259.9438698,210.3448318,
                       173.7977541,182.5497301,198.7985429,188.0458496,215.5709303),
            Groups = c(1, 1, 3, 3, 2, 3, 1, 3, 3, 2, 2))

For the plot I used:

df %>% arrange(Groups, Values) %>%
  mutate(name=factor(Groups, levels = Values)) %>%
  ggplot(aes(x = df$Sites, y = df$Values))+
  geom_bar(stat = "identity", fill = df$Groups)+
  scale_color_manual(values = c ('royalblue1', 'slategrey2', 'yellow1'))+
  ylab("Values")+
  xlab("")+
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

that resulted into:

enter image description here

but what I was expecting is the following:

enter image description here

Any help would be appreciated


Solution

  • Couple of issues in the code -

    • name=factor(Groups, levels = Values) gives all NA's. levels should be the value present in the data.
    • We don't need $ in ggplot code. Also df$Sites does not have the factor levels that we need. The factor levels are added in the piped data and not in the original data.
    library(dplyr)
    library(ggplot2)
    
    df %>% 
        arrange(Groups, Values) %>%
        mutate(Sites=factor(Sites, levels = Sites), 
               Groups = factor(Groups)) %>% 
        ggplot(aes(x = Sites, y = Values, fill = Groups)) +
        geom_bar(stat = "identity")+
        scale_fill_manual(values = c ('royalblue1', 'grey2', 'yellow1'))+
        ylab("Values")+
        xlab("")+
        theme(axis.text.x = element_text(angle = 90, hjust = 1))
    

    enter image description here