stacked bar ggplot with negative and positive values

1,394 views
Skip to first unread message

arnaud...@googlemail.com

unread,
Apr 24, 2015, 4:58:56 PM4/24/15
to ggp...@googlegroups.com
Hello

I am trying to produce a stacked bar plot with both positive and negative values. This post shows how to do this with ggplot2:

http://stackoverflow.com/questions/13734368/ggplot2-and-a-stacked-bar-chart-with-negative-values

I'd like all negative bars to be in shades of blue (with decreasing intensity towards the bottom of the plot), and all positive bars to be in shades of red (with increasing intensity towards the top of the plot). However I am having trouble specifying fills for the individual bars:

library(ggplot2)
library(RColorBrewer)

pos<-data.frame(month=rep(1:12, each=4), variable=paste("elem",rep(1:4, 12), "pos", sep="."), value=runif(4*12))
neg<-data.frame(month=rep(1:12, each=4), variable=paste("elem",rep(1:4, 12), "neg", sep="."), value=-runif(4*12))

brew<-c(brewer.pal(length(levels(pos$variable)), "Reds"), rev(brewer.pal(length(levels(neg$variable)), "Blues")))

ggplot() +
  geom_bar(data = pos, aes(x=month, y=value, fill=variable),stat = "identity") +
  geom_bar(data = neg, aes(x=month, y=value, fill=variable),stat = "identity") +
  scale_fill_manual(values=brew)

# problem: the levels are sorted by alphabetical order, and therefore both the legend and the colour ramps are not in the right order. So I tried to reorder the factors and to make sure they have the same levels in both data frames:

ord<-c(paste("elem", 1:4, "pos", sep="."), paste("elem", 4:1, "neg", sep="."))
pos$variable<-factor(pos$variable, levels=ord)
neg$variable<-factor(neg$variable, levels=ord)

ggplot() +
  geom_bar(data = pos, aes(x=month, y=value, fill=variable),stat = "identity") +
  geom_bar(data = neg, aes(x=month, y=value, fill=variable),stat = "identity") +
  scale_fill_manual(values=brew)

It does not change a thing. Could somebody help me?
Many thanks
Arnaud

a d

unread,
Apr 25, 2015, 8:57:28 AM4/25/15
to ggp...@googlegroups.com
OK, I have found a way to do it, so I am posting the solution for reference. It was a matter of correctly ordering the fill palette, the breaks and the bars:


pos<-data.frame(month=rep(1:12, each=4), variable=paste("elem",rep(1:4, 12), "pos", sep="."), value=runif(4*12))
neg<-data.frame(month=rep(1:12, each=4), variable=paste("elem",rep(1:4, 12), "neg", sep="."), value=-runif(4*12))

breaks<-c(levels(pos$variable), rev(levels(neg$variable)))

brew<-c(brewer.pal(length(unique(pos$variable)), "Reds"), rev(brewer.pal(length(unique(neg$variable)), "Blues")))
brew<-brew[order(xtfrm(breaks))]

ggplot() +
  geom_bar(data = pos, aes(x=month, y=value, fill=variable, order=-xtfrm(variable)),stat = "identity") +
  geom_bar(data = neg, aes(x=month, y=value, fill=variable, order=-xtfrm(variable)),stat = "identity") +
  scale_fill_manual(values=brew, breaks=breaks)+
  theme_bw()

Arnaud
Reply all
Reply to author
Forward
0 new messages