12

I'm trying to make a stacked bar graph with a facet_wrap, but I want the order of my stacked variables ("developed") to be flipped. I've reordered the factors, and tried "order=descend()," as well as "scale_fill_manual" and nothing seems to work.

Here is my code:

developed=rep(c("developed","available"),6)
agriculture=rep(c(rep("loi",2), rep("dryland",2), rep("agroforestry",2)),2)  
acres=c(7435,24254,10609,120500,10651,75606,6037,9910,4390,895,9747,46893)
islands=c(rep("All islands",6), rep("Oahu",6))
all_is2=data.frame(developed, agriculture, acres, islands)
head(all_is2)
  developed  agriculture  acres      island
1 developed          loi   7435 All islands
2 available          loi  24254 All islands
3 developed      dryland  10609 All islands
4 available      dryland 120500 All islands
5 developed agroforestry  10651 All islands
6 available agroforestry  75606 All islands

changing factor levels of "agriculture" and "developed"

all_is2$agriculture=factor(all_is2$agriculture,levels=c("loi","dryland","agroforestry"))
all_is2$developed=factor(all_is2$developed,levels=c("developed","available"))
levels(all_is2$developed)
[1] "developed" "available"

Then, plotting:

ggplot(all_is2,aes(x=agriculture,y=acres,fill=developed))+
     geom_bar(position="stack", stat="identity")+
     facet_wrap(~islands)+ scale_fill_grey(start=0.8, end=0.2, name="")+ xlab("")+ylab("Acres")+theme_bw()+ scale_y_continuous(labels=comma)

The Graph

I want the "developed" parts of the bars in gray on top of the "available" parts of the bars, which are black. And the legend should match the order of the bars as well.

Also, is it possible to move the facet_wrap "All islands" and "Oahu" at the top to the bottom of the graph under "loi" "dryland" and "agroforestry." Thank you for your help!!

Natalie K
  • 121
  • 1
  • 6
  • You need to reverse the order of your factors. (`levels=c("available","developed")`). And facets are always on top or besides the plot, if you want labels below an approach with grid.arrange might be the way to go. – Heroka Jan 11 '16 at 07:42
  • I've tried that, leaving the factors at levels=c("available","developed"), but what I get is the available stacked on top in gray and developed stacks on the bottom in black. (http://imgur.com/ne3iNhk) – Natalie K Jan 11 '16 at 07:48
  • Almost seems like a bug. – Mike Wise Jan 11 '16 at 08:26
  • On the facets, with thanks to @Jota: you can use `facet_wrap(~islands , switch = "x")` – Heroka Jan 11 '16 at 08:39
  • I think [this issue on ggplot github](https://github.com/hadley/ggplot2/issues/1472) is related. – Henrik Jan 11 '16 at 08:56
  • Thank you everyone i appreciate your help! – Natalie K Jan 11 '16 at 19:23

2 Answers2

11

This might be a solution.

What I did was ordering the dataset, so that the value I wanted to appear closest to the x-axis appeared first in the dataset. (I've used your ordering of factors here). This fixt the positioning of the bars.

Then, we had to change the colors and order of the legend. I could not wrap my head around scale_fill_grey, so I changed it to scale_fill_manual instead, setting both values and breaks.

ggplot(all_is2[rev(order(all_is2$developed)),] ,aes(x=agriculture,y=acres,fill=developed))+
  geom_bar(position="stack", stat="identity")+theme_bw()+
  facet_wrap(~islands)+ 
  scale_fill_manual(values=c(developed="grey80",available="grey20"),name="",
                    breaks=c("developed","available"))+
 xlab("")+ylab("Acres")

enter image description here

I don't know if it's a bug or a feature, and I think this also happened with previous versions in ggplot, but it appears that with stat_identity the first observation is plotted closest to the x-axis, the second on top of that etc.

Demonstration:

set.seed(123)
testdat <- data.frame(x=1,y=sample(5))


p1 <- ggplot(testdat, aes(x=x,y=y,fill=factor(y))) +geom_bar(stat="identity")+labs(title="order in dataset")
p2 <- ggplot(testdat[order(testdat$y),],aes(x=x,y=y,fill=factor(y))) +
  geom_bar(stat="identity") + labs(title="ordered by y")
p3 <- ggplot(testdat[rev(order(testdat$y)),],aes(x=x,y=y,fill=factor(y))) +
  geom_bar(stat="identity") + labs(title="reverse ordered by y")

enter image description here

Heroka
  • 12,889
  • 1
  • 28
  • 38
  • 2
    Oh, you beat me! Check out `facet_wrap(~islands , switch = "x")` for moving the facet labels below. It's a new feature of `ggplot2_2.0.0` – Jota Jan 11 '16 at 08:37
  • The fact you have to control the plot by ordering the dataset seems odd. But I thought it used `dplyr` internally, so it might be the same as mine. – Mike Wise Jan 11 '16 at 08:45
  • 1
    I used ggplot2.0; the `order`-aesthetic has been officially deprecated and someone suggesting ordering data to obtain the same effect. – Heroka Jan 11 '16 at 08:48
  • You're actually making it a bit more complicated than it needs to be; you just need to order the data and that's it. The order of the legend is controlled by the order of the factor levels; the order of the plot by the order of the data: http://ilari.scheinin.fi/ggplot-2-0-and-the-missing-order-aesthetic/ – Ilari Scheinin Jan 11 '16 at 10:31
  • Thank you everyone! I appreciate your help! @Heroka it worked! Thank you! – Natalie K Jan 11 '16 at 19:24
  • You're welcome! If it worked to your satisfaction, could you accept it? Keeps others from spending time on it. – Heroka Jan 11 '16 at 20:11
1

Fwiw, here is a solution with dplyr, and it uses scale_fill_manual to be explicit about the colors:

library(ggplot2)
library(dplyr)

developed=rep(c("developed","available"),6)
agriculture=rep(c(rep("loi",2), rep("dryland",2), rep("agroforestry",2)),2)  
acres=c(7435,24254,10609,120500,10651,75606,6037,9910,4390,895,9747,46893)
islands=c(rep("All islands",6), rep("Oahu",6))
all_is2=data.frame(developed, agriculture, acres, islands)

all_is2$agriculture=factor(all_is2$agriculture,levels=c("loi","dryland","agroforestry"))
#all_is2$developed=factor(all_is2$developed,levels=c("available","developed"))

all_is3 <- all_is2 %>% group_by(islands,agriculture,developed) %>% 
                       summarize(acres=sum(acres)) 

ggplot(all_is3,aes(x=agriculture,y=acres,fill=developed))+
  geom_bar(position="stack", stat="identity")+
  facet_wrap(~islands)+ 
  xlab("")+ylab("Acres")+theme_bw() +
  scale_fill_manual(name="",values=c("available"="black","developed"="light gray"))

enter image description here

Mike Wise
  • 22,131
  • 8
  • 81
  • 104
  • Your welcome, and I thought it was a good question from the start. I learned something from it. Glad to see you got all those upvotes too (one is mine), you are well established now. – Mike Wise Jan 11 '16 at 19:31
  • Yeah this was my first post because it was so aggravating, and I really couldn't find a solution online for days. But it was good to go through posting, I learned a lot too! – Natalie K Jan 11 '16 at 19:54
  • It must be morning there. I am ending my day :) – Mike Wise Jan 11 '16 at 19:58