4
votes

I would like to order the groups in both the legend and plot of a ggplot created with geom_bar.

Here is an example

mydata <- data.frame(mygroup = c('A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'), 
                     mysubgroup = c("north", "west", "south", "east", "north", "west", "south", "east"), 
                     value = c(5,10,6,12, 4, 4, 3, 5))

My starting point:

myplot <- ggplot(mydata, aes(mygroup, value, fill = mysubgroup)) + 
            geom_bar(position = "dodge", width = 0.5, stat = "identity")
myplot

enter image description here

I would like to have both the legend and the bars plotted in the order "north", "south", "east", "west".

I have tried adding scale_fill_discrete(limits = c("north", "south", "east", "west")) to the plot. It puts the legend in the desired order, but not the bars (although the bars are rearranged).

myplot + scale_fill_discrete(limits = c("north", "south", "east", "west"))

even if I reorder the data, I get the same result as above:

mydata2 <- mydata[c(1,3,4,2,5,7,8,6),]
myplot2 <- ggplot(mydata2, aes(mygroup, value, fill = mysubgroup)) + 
               geom_bar(position = "dodge", width = 0.5, stat = "identity") 
myplot2 + scale_fill_discrete(limits = c("north", "south", "east", "west"))

enter image description here

1
This is called "factor reordering", and it has been answered many a time on SO.Roman Luštrik
@RomanLuštrik I saw the following potential duplicates: stackoverflow.com/questions/6901405/…, stackoverflow.com/questions/8713462/…, stackoverflow.com/questions/7299440/…, but couldn't find any that explicitly dealt with groups and subgroups. Perhaps should be closed as dupe, but I think this additional example will be more helpful than confusing.Abe

1 Answers

4
votes

I figured out the answer while writing the question (and will post as a CW to invite contributions)...

The answer is to have the subgroup be a "factor" with the levels in the desired order:

mydata <- data.frame(mygroup = c('A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'), 
                     mysubgroup = factor(c("north", "west", "south", "east", 
                                           "north", "west", "south", "east"), 
                                          levels = c("north", "south", "east", "west")), 
                     value = c(5,10,6,12, 4, 4, 3, 5))

ggplot(mydata, aes(mygroup, value, fill = mysubgroup)) + 
            geom_bar(position = "dodge", width = 0.5, stat = "identity")