Search code examples
rggplot2tidyversestacked-bar-chart

R ggplot2 | Sorting a stacked barplot by count when data is introduced through fill


I want to make a barplot from just one column of a dataframe.

This ↓ is the relevant data:

df  Most_liked_Male
1   Mallika 207 
2   Mallika 207 
3   Mallika 207 
4  Namaskar G 81
5   Mallika 207 
6   Mallika 207 
7   Mallika 207 
8     Partech 28
9     Partech 29
10  Mallika 207 
11       Mallika
12     Narasimha
13       Mallika
14       Mallika
15       Mallika
16       Mallika
17       Mallika
18       Mallika
19       Mallika
20       Mallika
21       Suraj-2
22       Mallika
23   Mallika-207
24       Mallika
25        Bhakti
26        Bhakti
27       Mallika
28        Bhakti
29        Bhakti
30       Mallika
31        Bhakti 

This gives me a stacked barplot:

library(tidyverse)
df$dummy <- c("dummy")

ggplot(data = df, aes(x = dummy, fill = Most_liked_Male)) + 
  geom_bar() 

corresponding graph

This way the segments of the bar are in alphabetical order - I want it to be sorted by count. I have only found solutions that require data to be fed into aes() by assigning them directly to the x-axis (I tried to generate the barplot this way, but couldn't get it to work with this data). So, how can I sort the segments of the bar, when my data is introduced through "fill".

In my data are three more columns, like the one I showed in the example. If someone knows a way to implement them as additional stacked bars into one graphic that would be very helpful as well, but I can also work with generating distinct graphs for each column.


Solution

  • For the first part of your question, you can create a new count column and then call it in fill with a reorder(), as follows

    df <- df %>%
      group_by(Most_liked_Male) %>%
      mutate(n = n())
    
    ggplot(data = df, aes(x=dummy, fill = reorder(Most_liked_Male, n))) +
      geom_bar()
    

    For the second part, you can consider pivot_longer() on the different columns you want to visualize in the same plot.

    ## fake creation of a new column in df
    df <- df %>%
      ungroup() %>%
      mutate(same_type_of_column = sample(x = Most_liked_Male, nrow(x = df), replace = TRUE))
    
    ## pivoting operation
    df <- df %>%
      pivot_longer(cols = c(Most_liked_Male, same_type_of_column), names_to = "column_name", values_to = "values") %>%
      group_by(values) %>% # grouping as before
      mutate(n = n()) # count as before
    
    # plot
    ggplot(data = df, aes(x=dummy, fill = reorder(values, n))) +
      geom_bar()