2019-11-01

How to change the stacking order in a stacked bar chart in ggplot2

Problem

We want to control the stacking order of a stacked bar created with ggplot2.

  • Original chart
  • By default the bars are stacked in alphabetical order based on the variable passed on to the argument fill.

    library(reshape2)
    library(ggplot2)
    ra.melt <- melt(ra)
    p <- ggplot(ra.melt, aes(x = variable, y = value))
    p + geom_bar(aes(fill = quality), stat = "identity") + 
      labs(x = "group", y = "percentage (%)")
    
    We double-check the levels of the variable quality.

    levels(ra.melt$quality)
    
     [1] "A"     "B"     "C"     "D"     "E"     "F"    
     [7] "G"     "H"     "I"     "J"     "K"     "L"    
    [13] "M"     "other"
    
  • Data
  • ra <- structure(list(quality = structure(c(2L, 6L, 13L, 1L, 7L, 5L, 
    10L, 4L, 3L, 9L, 11L, 12L, 8L, 14L), .Label = c("A", "B", "C", 
    "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "other"), class = "factor"), GY = c(25.5932389, 13.9567819, 11.7333, 8.6439, 7.8351008, 
        8.29, 6.059643, 3.8608517, 4.3277, 3.1710598, 1.2021144, 
        1.0986329, 0.9369271, 3.2907496), TH = c(23.0215577, 15.8975387, 
        10.5075, 7.8888, 8.8121504, 8.276, 6.4356378, 3.9147685, 
        5.4838, 3.9339386, 1.3921565, 0.742406, 0.8795013, 2.8142444
        ), SZ = c(21.217152, 16.0363831, 11.154, 8.5094, 7.945884, 
        10.2717, 5.4962929, 4.1381946, 5.1141, 3.4053352, 1.8472827, 
        1.0648934, 0.9792861, 2.820096), DZ = c(23.7548859, 14.4732136, 
        12.1292, 10.4722, 8.0838209, 7.0575, 5.144598, 4.174118, 
        5.4004, 3.1940577, 1.4427867, 1.1323864, 0.8986281, 2.6422047
        ), FP = c(19.9848602, 16.420735, 12.9683, 11.2059, 7.5143706, 
        6.8747, 5.8653262, 5.5412901, 4.182, 3.5347168, 1.3838249, 
        0.8811604, 0.8585596, 2.7842562)), .Names = c("quality", 
    "GY", "TH", "SZ", "DZ", "FP"), class = "data.frame", row.names = c("1", 
    "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", 
    "14"))
    
       quality         GY         TH         SZ         DZ         FP
    1        B 25.5932389 23.0215577 21.2171520 23.7548859 19.9848602
    2        F 13.9567819 15.8975387 16.0363831 14.4732136 16.4207350
    3        M 11.7333000 10.5075000 11.1540000 12.1292000 12.9683000
    4        A  8.6439000  7.8888000  8.5094000 10.4722000 11.2059000
    5        G  7.8351008  8.8121504  7.9458840  8.0838209  7.5143706
    6        E  8.2900000  8.2760000 10.2717000  7.0575000  6.8747000
    7        J  6.0596430  6.4356378  5.4962929  5.1445980  5.8653262
    8        D  3.8608517  3.9147685  4.1381946  4.1741180  5.5412901
    9        C  4.3277000  5.4838000  5.1141000  5.4004000  4.1820000
    10       I  3.1710598  3.9339386  3.4053352  3.1940577  3.5347168
    11       K  1.2021144  1.3921565  1.8472827  1.4427867  1.3838249
    12       L  1.0986329  0.7424060  1.0648934  1.1323864  0.8811604
    13       H  0.9369271  0.8795013  0.9792861  0.8986281  0.8585596
    14   other  3.2907496  2.8142444  2.8200960  2.6422047  2.7842562
    

Solution

  • Stacked in the data frame's original order
  • ra.melt$quality <- factor(ra.melt$quality, levels = ra$quality)
    p <- ggplot(ra.melt, aes(x = variable, y = value))
    p + geom_bar(aes(fill = quality), stat = "identity") + 
        labs(x = "group", y = "percentage (%)")
    
    factor(ra.melt$quality, levels = ra$quality)
    
     [1] B     F     M     A     G     E     J     D    
     [9] C     I     K     L     H     other B     F    
    [17] M     A     G     E     J     D     C     I    
    [25] K     L     H     other B     F     M     A    
    [33] G     E     J     D     C     I     K     L    
    [41] H     other B     F     M     A     G     E    
    [49] J     D     C     I     K     L     H     other
    [57] B     F     M     A     G     E     J     D    
    [65] C     I     K     L     H     other
    Levels: B F M A G E J D C I K L H other
    
  • In reverse order
  • ra.melt$quality <- factor(ra.melt$quality, levels = rev(ra$quality))
    p <- ggplot(ra.melt, aes(x = variable, y = value))
    p + geom_bar(aes(fill = quality), stat = "identity") +  
        labs(x = "group", y = "percentage (%)")
    
    factor(ra.melt$quality, levels = rev(ra$quality))
    
     [1] B     F     M     A     G     E     J     D    
     [9] C     I     K     L     H     other B     F    
    [17] M     A     G     E     J     D     C     I    
    [25] K     L     H     other B     F     M     A    
    [33] G     E     J     D     C     I     K     L    
    [41] H     other B     F     M     A     G     E    
    [49] J     D     C     I     K     L     H     other
    [57] B     F     M     A     G     E     J     D    
    [65] C     I     K     L     H     other
    Levels: other H L K I C D J E G A M F B
    
    Alternatively we can use the function fct_rev

    library(forcats)
    p <- ggplot(ra.melt, aes(x = variable, y = value))
    p + geom_bar(aes(fill = fct_rev(quality)), stat = "identity") + 
      labs(x = "group", y = "percentage (%)")
    
  • If we'd like to reverse the stacked order but but keeping the order of the legend, we use the argument position_stack(reverse = TRUE)
  • p <- ggplot(ra.melt, aes(x = variable, y = value))
    p + geom_bar(aes(fill = fct_rev(quality)), stat = "identity", position = position_stack(reverse = TRUE)) + labs(x = "group", y = "percentage (%)")
    

Referencias

Related posts

2 comentarios:

  1. Gracias!! me estaba enloqueciendo, no hallaba respuesta en ningun lado.

    ResponderEliminar

Nube de datos