Home > Back-end >  How to rank/order bars in barchart ggplot?
How to rank/order bars in barchart ggplot?

Time:06-28

I have 2 numerical (sales; cost) and 2 categorical (model; level) variables:

   model level sale cost    Colour
1      A  HIGH  100 -110     black
2      B  HIGH  120  -89    khaki1
3      C  HIGH  500  -20       red
4      D  HIGH  455 -300     green
5      E  HIGH  456 -110 chocolate
6      F  HIGH   12 -120    orange
7      G  HIGH   56  -56      blue
8      H  HIGH   98 -300      gold
9    All  HIGH  889 -790    sienna
10     Z  HIGH  456  -30    yellow
11     A   LOW  432  -70     black
12     B   LOW  567  -40    khaki1
13     C   LOW  345  -30       red
14     D   LOW  345 -120     green
15     E   LOW  100  -10 chocolate
16     F   LOW   67  -21    orange
17     G   LOW   34  -24      blue
18     H   LOW  110 -540      gold
19   All   LOW  670 -123    sienna
20     Z   LOW  160  -45    yellow

Next I built barchart with negative and positive bars, which is split into 2 part according to level column and ranked from TOP to Down by sales

ggplot()  
  geom_col(aes(value, tidytext::reorder_within(model, value, level),
               fill = model, color = model), 
           data = df[df$sign == "sale", ],
           position = "stack")   
  scale_fill_manual(values = Colour, breaks = df$model)  
  scale_color_manual(values = Colour, breaks = df$model) 
  geom_col(aes(value, tidytext::reorder_within(model, value, level),
               color = model), 
           data = df[df$sign == "cost", ], 
           fill = "white",
           position = "stack")  
  tidytext::scale_y_reordered()  
  labs(fill = "model")  
  facet_grid(level ~ ., switch = "y",scales = "free_y")  
  theme(axis.text.x = element_text(angle = 90),
        strip.background = element_rect(fill = "white"),
        strip.placement = "outside",
        strip.text.y.left = element_text(angle = 0),
        panel.spacing = unit(0, "lines"))   
  theme(legend.position="none")   
  labs(y = " ")   geom_vline(xintercept = 0,linetype="dotted", color="white")

Now I want to set Z row always in the end on the plot and All always on the TOP:

enter image description here

CodePudding user response:

One option to achieve your desired result would be to add a helper value column to your data where you assign a value of e.g. -Inf to Z and which is used to set the order of the categories. This way Z will be put at the last position.

Note: I removed scale_color/fill_manual as you haven't provided your colors.

library(ggplot2)

df <- df |> 
  tidyr::pivot_longer(c(sale, cost), names_to = "sign") |> 
  dplyr::mutate(value1 = ifelse(model == "Z", -Inf, value))


ggplot()  
  geom_col(aes(value, tidytext::reorder_within(model, value1, level),
               fill = model, color = model), 
           data = df[df$sign == "sale", ],
           position = "stack")   
  geom_col(aes(value, tidytext::reorder_within(model, value1, level),
               color = model), 
           data = df[df$sign == "cost", ], 
           fill = "white",
           position = "stack")  
  tidytext::scale_y_reordered()  
  labs(fill = "model")  
  facet_grid(level ~ ., switch = "y",scales = "free_y")  
  theme(axis.text.x = element_text(angle = 90),
        strip.background = element_rect(fill = "white"),
        strip.placement = "outside",
        strip.text.y.left = element_text(angle = 0),
        panel.spacing = unit(0, "lines"))   
  theme(legend.position="none")   
  labs(y = " ")   geom_vline(xintercept = 0,linetype="dotted", color="white")

DATA

structure(list(model = c("A", "B", "C", "D", "E", "F", "G", "H", 
"All", "Z", "A", "B", "C", "D", "E", "F", "G", "H", "All", "Z"
), level = c("HIGH", "HIGH", "HIGH", "HIGH", "HIGH", "HIGH", 
"HIGH", "HIGH", "HIGH", "HIGH", "LOW", "LOW", "LOW", "LOW", "LOW", 
"LOW", "LOW", "LOW", "LOW", "LOW"), sale = c(100L, 120L, 500L, 
455L, 456L, 12L, 56L, 98L, 889L, 456L, 432L, 567L, 345L, 345L, 
100L, 67L, 34L, 110L, 670L, 160L), cost = c(-110L, -89L, -20L, 
-300L, -110L, -120L, -56L, -300L, -790L, -30L, -70L, -40L, -30L, 
-120L, -10L, -21L, -24L, -540L, -123L, -45L), Colour = c("black", 
"khaki1", "red", "green", "chocolate", "orange", "blue", "gold", 
"sienna", "yellow", "black", "khaki1", "red", "green", "chocolate", 
"orange", "blue", "gold", "sienna", "yellow")), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", 
"14", "15", "16", "17", "18", "19", "20"))
  • Related