ggplot reorder stacked bar plot based on values in data frame

4k views Asked by At

I am making stacked bar plots with ggplot2 in R with specific bar ordering about the y-axis.

# create reproducible data
library(ggplot2)
d <- read.csv(text='Day,Location,Length,Amount
            1,4,3,1.1
            1,3,1,2
            1,2,3,4
            1,1,3,5
            2,0,0,0
            3,3,3,1.8
            3,2,1,3.54
            3,1,3,1.1',header=T)

ggplot(d, aes(x = Day, y = Length)) + geom_bar(aes(fill = Amount, order = Location), stat = "identity")

ggplot(d, aes(x = Day, y = Length)) + geom_bar(aes(fill = Amount, order = rev(Location)), stat = "identity")

The first ggplot plot shows the data in order of Location, with Location=1 nearest the x-axis and data for each increasing value of Location stacked upon the next.

The second ggplot plot shows the data in a different order, but it doesn't stack the data with the highest Location value nearest the x-axis with the data for the next highest Location stacked in the second from the x-axis position for the first bar column, like I would expect it to based on an earlier post.

This next snippet does show the data in the desired way, but I think this is an artifact of the simple and small example data set. Stacking order hasn't been specified, so I think ggplot is stacking based on values for Amount.

ggplot(d, aes(x = Day, y = Length)) + geom_bar(aes(fill = Amount), stat = "identity")

What I want is to force ggplot to stack the data in order of decreasing Location values (Location=4 nearest the x-axis, Location=3 next, ... , and Location=1 at the very top of the bar column) by calling the order = or some equivalent argument. Any thoughts or suggestions?

It seems like it should be easy because I am only dealing with numbers. It shouldn't be so hard to ask ggplot to stack the data in a way that corresponds to a column of decreasing (as you move away from the x-axis) numbers, should it?

1

There are 1 answers

0
BrodieG On BEST ANSWER

Try:

ggplot(d, aes(x = Day, y = Length)) + 
  geom_bar(aes(fill = Amount, order = -Location), stat = "identity")

Notice how I swapped rev with -. Using rev does something very different: it stacks by the value for each row you happen to get if you reverse the order of values in the column Location, which could be just about anything.