How do you order the fill-colours within ggplot2 geom_bar

RGraphicsGgplot2

R Problem Overview


I am calling the ggplot function

ggplot(data,aes(x,y,fill=category)+geom_bar(stat="identity")

The result is a barplot with bars filled by various colours corresponding to category. However the ordering of the colours is not consistent from bar to bar. Say there is pink, green and blue. Some bars go pink,green,blue from bottom to top and some go green,pink,blue. I don't see any obvious pattern.

How are these orderings chosen? How can I change it? At the very least, how can I make ggplot choose a consistent ordering?

The class of (x,y and category) are (integer,numeric and factor) respectively. If I make category an ordered factor, it does not change this behavior.

Anyone know how to fix this?

Reproducible example:

dput(data)

structure(list(mon = c(9L, 10L, 11L, 10L, 8L, 7L, 7L, 11L, 9L, 
10L, 12L, 11L, 7L, 12L, 8L, 12L, 9L, 7L, 9L, 10L, 10L, 8L, 12L, 
7L, 11L, 10L, 8L, 7L, 11L, 12L, 12L, 9L, 9L, 7L, 7L, 12L, 12L, 
9L, 9L, 8L), gclass = structure(c(9L, 1L, 8L, 6L, 4L, 4L, 3L, 
6L, 2L, 4L, 1L, 1L, 5L, 7L, 1L, 6L, 8L, 6L, 4L, 7L, 8L, 7L, 9L, 
8L, 3L, 5L, 9L, 2L, 7L, 3L, 5L, 5L, 7L, 7L, 9L, 2L, 4L, 1L, 3L, 
8L), .Label = c("Down-Down", "Down-Stable", "Down-Up", "Stable-Down", 
"Stable-Stable", "Stable-Up", "Up-Down", "Up-Stable", "Up-Up"
), class = c("ordered", "factor")), NG = c(222614.67, 9998.17, 
351162.2, 37357.95, 4140.48, 1878.57, 553.86, 40012.25, 766.52, 
15733.36, 90676.2, 45000.29, 0, 375699.84, 2424.21, 93094.21, 
120547.69, 291.33, 1536.38, 167352.21, 160347.01, 26851.47, 725689.06, 
4500.55, 10644.54, 75132.98, 42676.41, 267.65, 392277.64, 33854.26, 
384754.67, 7195.93, 88974.2, 20665.79, 7185.69, 45059.64, 60576.96, 
3564.53, 1262.39, 9394.15)), .Names = c("mon", "gclass", "NG"
), row.names = c(NA, -40L), class = "data.frame") 

ggplot(data,aes(mon,NG,fill=gclass))+geom_bar(stat="identity")

R Solutions


Solution 1 - R

Starting in ggplot2_2.0.0, the order aesthetic is no longer available. To get a graph with the stacks ordered by fill color, you can simply order the dataset by the grouping variable you want to order by.

I often use arrange from dplyr for this. Here I'm ordering the dataset by the fill factor within the ggplot call rather than creating an ordered dataset but either will work fine.

library(dplyr)

ggplot(arrange(data, gclass), aes(mon, NG, fill = gclass)) +
	geom_bar(stat = "identity")

This is easily done in base R, of course, using the classic order with the extract brackets:

ggplot(data[order(data$gclass), ], aes(mon, NG, fill = gclass)) +
	geom_bar(stat = "identity")

With the resulting plot in both cases now in the desired order: enter image description here

ggplot2_2.2.0 update

In ggplot_2.2.0, fill order is based on the order of the factor levels. The default order will plot the first level at the top of the stack instead of the bottom.

If you want the first level at the bottom of the stack you can use reverse = TRUE in position_stack. Note you can also use geom_col as shortcut for geom_bar(stat = "identity").

ggplot(data, aes(mon, NG, fill = gclass)) +
	geom_col(position = position_stack(reverse = TRUE))

Solution 2 - R

You need to specify the order aesthetic as well.

ggplot(data,aes(mon,NG,fill=gclass,order=gclass))+
    geom_bar(stat="identity")

enter image description here

This may or may not be a bug.

Solution 3 - R

To order, you must use the levels parameter and inform the order. Like this:

data$gclass
(data$gclass2 <- factor(data$gclass,levels=sample(levels(data$gclass)))) # Look the difference in the factors order
ggplot(data,aes(mon,NG,fill=gclass2))+geom_bar(stat="identity")

Solution 4 - R

You can change the colour using the scale_fill_ functions. For example:

ggplot(dd,aes(mon,NG,fill=gclass)) + 
  geom_bar(stat="identity") + 
  scale_fill_brewer(palette="blues")

To get consistent ordering in the bars, then you need to order the data frame:

dd = dd[with(dd, order(gclass, -NG)), ]

In order to change the ordering of legend, alter the gclass factor. So something like:

dd$gclass= factor(dd$gclass,levels=sort(levels(dd$gclass), TRUE))

enter image description here

Solution 5 - R

Building on @aosmith 's answer, another way to order the bars, that I found slightly more intuitive is:

ggplot(data, aes(x=mon, y=reorder(NG,gclass), fill = gclass)) +
    geom_bar(stat = "identity")

The beauty of the reorder function from the base stats package is that you can apply it in the reorder(based_on_dimension, y, function) wherein y is ordered based_on_dimension with a function like sum, mean, etc.

Solution 6 - R

Since this exchange shows up first for "factor fill order", I will add one more solution, what I believe to be a bit more straight forward, and doesn't require altering your underlying data.

ggplot(data,aes(x,y,fill=factor(category, levels = c("Down-Down", "Down-Stable", "Down-Up", "Stable-Down", "Stable-Stable", "Stable-Down", "Up-Down", "Up-Stable", "Up-Up"))) + 
geom_col(position = position_stack(reverse = FALSE))

Or as I prefer, I first create a variable vector to simplify coding later and make it more easily editable:

v_factor_levels <- c("Down-Down", "Down-Stable", "Down-Up", "Stable-Down", "Stable-Stable", "Stable-Down", "Up-Down", "Up-Stable", "Up-Up")

ggplot(data,aes(x,y,fill=factor(category, levels = v_factor_levels)) + 
geom_col(position = position_stack(reverse = FALSE))

You don't need the reverse position element within geom_col(), I keep these as a reminder in case I want to reverse, but you could further simplify by eliminating that.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDave31415View Question on Stackoverflow
Solution 1 - RaosmithView Answer on Stackoverflow
Solution 2 - RBrian DiggsView Answer on Stackoverflow
Solution 3 - RRcosterView Answer on Stackoverflow
Solution 4 - RcsgillespieView Answer on Stackoverflow
Solution 5 - RMallika GokarnView Answer on Stackoverflow
Solution 6 - Rglenn_in_bostonView Answer on Stackoverflow