Reverse stacked bar order
Asked Answered
A

2

66

I'm creating a stacked bar chart using ggplot like this:

plot_df <- df[!is.na(df$levels), ] 
ggplot(plot_df, aes(group)) + geom_bar(aes(fill = levels), position = "fill")

Which gives me something like this:

enter image description here

How do I reverse the order the stacked bars themselves, so that level 1 is at the bottom, and level 5 is at the top of each bar?

I've seen a number of questions on this (e.g. How to control ordering of stacked bar chart using identity on ggplot2) and the common solution seems to be to reorder the dataframe by that level as that what ggplot is using the determine the order

So I've tried reordering using dplyr:

plot_df <- df[!is.na(df$levels), ] %>% arrange(desc(levels))

However, the plot comes out the same. It also doesn't seem to make a difference whether I arrange by ascending or descending order

Here is a reproducible example:

group <- c(1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4)
levels <- c("1","1","1","1","2","2","2","2","3","3","3","3","4","4","4","4","5","5","5","5","1","1","1","1")
plot_df <- data.frame(group, levels)

ggplot(plot_df, aes(group)) + geom_bar(aes(fill = levels), position = "fill")
Aurelie answered 10/3, 2017 at 4:8 Comment(4)
The order of the observations makes no sense, but the order of the factor levels does. Also, reprex.Marquess
yes, I have also tried changing the factor level order with levels(plot_df$levels) <- c("1", "2", "3", "4", "5") (and the reverse order) but it doesn't change the graph orderAurelie
Also added an example of the dataAurelie
plot_df %>% mutate(levels = factor(levels, levels = 5:1)) %>% ggplot(aes(group, fill = levels)) + geom_bar(position = "fill") or just ggplot(plot_df, aes(group)) + geom_bar(aes(fill = levels), position = position_fill(reverse = TRUE))Marquess
P
99

The release notes of ggplot2 version 2.2.0 on Stacking bars suggest:

If you want to stack in the opposite order, try forcats::fct_rev()

library(ggplot2)   # version 2.2.1 used    
plot_df <- data.frame(group = rep(1:4, 6),
                      levels = factor(c(rep(1:5, each = 4), rep(1, 4))))
ggplot(plot_df, aes(group, fill = forcats::fct_rev(levels))) + 
  geom_bar(position = "fill")

Reverse levels

This is the original plot:

ggplot(plot_df, aes(group, fill = levels)) + 
  geom_bar(position = "fill")

Original plot

Or, using position_fill(reverse = TRUE) as suggested by alistaire in his comment:

ggplot(plot_df, aes(group, fill = levels)) + 
  geom_bar(position = position_fill(reverse = TRUE))

enter image description here

Note that the levels (colors) in the legend is not in the same order as in the stacked bars.

Prae answered 10/3, 2017 at 7:58 Comment(1)
position_fill(reverse = TRUE) normalizes bars, use position_stack(reverse = TRUE) if you don't want to normalize bars.Gymnasiast
L
0

An alternative is to reorder the factor as such, assuming the factor is called "levels": levels = ordered(levels, levels=c(5,4,3,2,1)). for more info: http://www.cookbook-r.com/Manipulating_data/Changing_the_order_of_levels_of_a_factor/

Landre answered 5/3, 2021 at 17:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.