4

Is there a way to specify that I want the bars of a stacked bar graph in with ggplot ordered in terms of the total of the four factors from least to greatest? (so in the code below, I want to order by the total of all of the variables) I have the total for each x value in a dataframe that that I melted to create the dataframe from which I formed the graph.

The code that I am using to graph is:

ggplot(md, aes(x=factor(fullname), fill=factor(variable))) + geom_bar()

My current graph looks like this:

http://i.minus.com/i5lvxGAH0hZxE.png

The end result is I want to have a graph that looks a bit like this:

http://i.minus.com/kXpqozXuV0x6m.jpg

My data looks like this:

data in chart
(source: minus.com)

and I melt it to this form where each student has a value for each category:

melted data http://i.minus.com/i1rf5HSfcpzri.png

before using the following line to graph it

       ggplot(data=md, aes(x=fullname, y=value, fill=variable), ordered=TRUE) + geom_bar()+ opts(axis.text.x=theme_text(angle=90)) 

Now, I'm not really sure that I understand the way Chi does the ordering and if I can apply that to the data from either of the frames that I have. Maybe it's helpful that that the data is ordered in the original data frame that I have, the one that I show first.

UPDATE: We figured it out. See this thread for the answer: Order Stacked Bar Graph in ggplot

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Michael Discenza
  • 3,240
  • 7
  • 30
  • 41
  • 3
    Also a simple way to account for the overlapping labels is to change the orientation of the bars from vertical to horizontal. I've seen some people suggest this anyway as many languages read left to right (and bar orientation doesn't seem to have any appreciable impact on interpretation). – Andy W Nov 11 '11 at 17:36
  • @mdiscenza: You can edit your original question to add those missing details instead of trying to edit chl's answer. – hugomg Nov 15 '11 at 16:22
  • Oops, sorry, still trying to figure out the protocol here. Thanks. – Michael Discenza Nov 15 '11 at 16:49

1 Answers1

6

I'm not sure about the way your data were generated (i.e., whether you use a combination of cast/melt from the reshape package, which is what I suspect given the default name of your variables), but here is a toy example where sorting is done outside the call to ggplot. There might be far better way to do that, browse on SO as suggested by @Andy.

v1 <- sample(c("I","S","D","C"), 200, rep=T)
v2 <- sample(LETTERS[1:24], 200, rep=T)
my.df <- data.frame(v1, v2)
idx <- order(apply(table(v1, v2), 2, sum))

library(ggplot2)
ggplot(my.df, aes(x=factor(v2, levels=LETTERS[1:24][idx], ordered=TRUE),
       fill=v1)) + geom_bar() + opts(axis.text.x=theme_text(angle=90)) +
       labs(x="fullname")

To sort in the reverse direction, add decr=TRUE with the order command. Also, as suggested by @Andy, you might overcome the problem with x-labels overlap by adding + coord_flip() instead of the opts() option.

enter image description here

chl
  • 27,771
  • 5
  • 51
  • 71
  • something like `reorder(f,rep(1,length(f)),sum)` will create a factor with levels ordered by frequency ... – Ben Bolker Nov 11 '11 at 23:13
  • Thanks @BenBolker. I didn't manage to get this working in this particular configuration. Incidentally, one of Andy's comments which pointed to a [related thread](http://stackoverflow.com/questions/6901405/r-ggplot-ordering-bars-in-barplot-like-plot/6901630#6901630), here on SO, disappeared during the migration (don't know why!). – chl Nov 12 '11 at 11:47
  • 3
    `ggplot(my.df, aes(x=reorder(v2,rep(1,length(v2)),sum),fill=v1)) + geom_bar() + opts(axis.text.x=theme_text(angle=90)) + labs(x="fullname")` works for me (without doing any other reordering of the factor) – Ben Bolker Nov 12 '11 at 13:01
  • @Ben (+1) Thanks. That's really more elegant, indeed. – chl Nov 12 '11 at 16:03