Search code examples
rggplot2plotbar-chart

Reorder bar plot in ggplot R, by Frequency AND Alphabetically


Bar plot in ggplot are automatically arranged alphabetically. My plots are actually plotted alphabetically inverted and I can invert the alphabetical order and make it forward. If i put the condition to order the plot by frequency, classes with the same frequency appear in the plot in the counter-alphabetical order.

This is what the plot does:

G - 60
T - 50
C - 40
B - 40
A - 40

This is what i need from the plot:

G - 60
T - 50
A - 40
B - 40
C - 40

This i the code I've written to order the plot by frequency and i cannot figure out an alternative that works. I see that it's possible to add a function to "reorder" but i don't know how to use it here.

ggplot(data) +
 aes(x = reorder(Names, Frequency), y = Frequency)

EDIT

Data:

fam_sub <- structure(
  list(
    Abs_fam.Var1 = c(
      "Apio",
      "Myria",
      "Xyla",
      "Rhyti",
      "Hypo",
      "Phaci"
    ),
    Abs_fam.Freq = c(1L, 1L, 1L, 2L, 8L, 53L)
  ),
  row.names = c(NA,-6L),
  groups = structure(
    list(
      Abs_fam.Freq = c(1L, 2L, 8L, 53L),
      .rows = structure(
        list(1:3, 4L, 5L, 6L),
        ptype = integer(0),
        class = c("vctrs_list_of",
                  "vctrs_vctr", "list")
      )
    ),
    class = c("tbl_df", "tbl", "data.frame"),
    row.names = c(NA,-4L),
    .drop = TRUE
  ),
  class = c("grouped_df",
            "tbl_df", "tbl", "data.frame"))

Plot code:

library(ggplot2)

ggplot(fam_sub, aes(x = reorder(Abs_fam.Var1, Abs_fam.Freq), y = Abs_fam.Freq)) +
  geom_col(fill = "#559355") +
  coord_flip() +
  theme_minimal()

Solution

  • I'm sure there are more elegant ways to do it but this is may be an option. What i did was assign levels based on first value of the column "Abs_fam.Freq" followed by alphabetical order of "Abs_fam.Var1".

    library(tidyverse)
        
    lvs <- arrange(fam_sub, Abs_fam.Freq, desc(Abs_fam.Var1))$Abs_fam.Var1
        
    fam_sub_2 <- fam_sub %>%
          mutate(Abs_fam.Var1 = factor(Abs_fam.Var1, levels = lvs))
        
    ggplot(fam_sub_2, aes(x = Abs_fam.Var1, y = Abs_fam.Freq)) +
          geom_col(fill = "#559355") +
          coord_flip() +
          theme_minimal()
    

    enter image description here