cherrytree
cherrytree

Reputation: 1591

ggplot2 stacked bar not ordering by manually-defined factor order

I would like to manually define the order of the items in each stacked bar. From all of the research I've done, I should be able to do this by manually defining the order of these factors prior to plotting. For some reason I have not been successful.

Here is the raw data:

df <- structure(list(cross_valid = structure(c(1L, 2L, 1L, 2L, 1L, 
2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L), .Label = c("1", 
"2"), class = "factor"), variable = structure(c(1L, 1L, 2L, 2L, 
3L, 3L, 4L, 4L, 5L, 5L, 6L, 6L, 7L, 7L, 8L, 8L, 9L, 9L), .Label = c("a", 
"b", "c", "d", "e", "f", "g", "h", "i"), class = "factor"), value = c(0, 
0, 0, 0, 3.546, 0, 0, 0, 28.0927688833, 4.689, 0.4887, 1.134, 
20.886690705, 16.8620595883, 14.8086, 18.648, 20.5713, 44.046
)), row.names = c(NA, -18L), class = "data.frame", .Names = c("cross_valid", 
"variable", "value"))

Looks like:

> head (df)
  cross_valid variable value
1           1        a 0.000
2           2        a 0.000
3           1        b 0.000
4           2        b 0.000
5           1        c 3.546
6           2        c 0.000

Current order and levels of df$variable:

> df$variable
 [1] a a b b c c d d e e f f g g h h i i
Levels: a b c d e f g h i

Now I change the order of df$variable:

df$variable <- factor(df$variable, levels = unique(c("i","a","b","e","g","f","h")),ordered=TRUE)

Now plot the graph:

library(ggplot2)
p <- ggplot() + geom_bar(data=df,aes(x=cross_valid,y=value,fill=variable),stat='identity')
p <- p + scale_fill_manual("",values=c('a'='darkred','b'='blue','c'='black','d'='darkolivegreen1','e'='green','f'='darkorchid','g'='yellow',
                                       'h'='snow4','i'='darkgray'),
                           breaks=c('i','h','g','f','e','d','c','b','a'),
                           labels=c('i','h','g','f','e','d','c','b','a'))
p

Which produces the following plot:

enter image description here

I defined 'i' and 'h' to be on opposite ends of the bar, yet they are still next to each other. Are there any ideas on why this might be happening? Maybe something is odd with my data?

Thanks

-al

EDIT 1:

Following @MrFlick's advice I removed breaks, but still find that 'i' and 'h' are still next to each other in the bar, even though the levels have defined them to be at opposite ends of the bar.

> df$variable
 [1] a a b b c c d d e e f f g g h h i i
Levels: i < a < b < c < d < e < g < f < h

Edited plot code:

p <- ggplot() + geom_bar(data=df,aes(x=cross_valid,y=value,fill=variable),stat='identity')
p <- p + scale_fill_manual("",values=c('a'='darkred','b'='blue','c'='black','d'='darkolivegreen1','e'='green','f'='darkorchid','g'='yellow',
                                       'h'='snow4','i'='darkgray'))
p

Produces:

enter image description here

Upvotes: 5

Views: 6838

Answers (1)

Daniel
Daniel

Reputation: 7832

Following works for me:

df$variable <- relevel(df$variable, "i")

library(ggplot2)
p <- ggplot() + 
  geom_bar(data=df,aes(x=cross_valid,y=value,fill=variable,order=variable),stat='identity') +
  scale_fill_manual("",
                    values=c('a'='darkred','b'='blue','c'='black','d'='darkolivegreen1','e'='green','f'='darkorchid','g'='yellow','h'='snow4','i'='darkgray'),
                    breaks=c('h','g','f','e','d','c','b','a','i'),
                    labels=c('h','g','f','e','d','c','b','a','i'))
p

I used relevel to change factor level order and added an order parameter to the aes. Edit: Changing the order of breaks and labels also adjusts the legend accordingly.

enter image description here

Second Edit: Sorry, solution was already posted in comments above, didn't see that before answering...

Upvotes: 3

Related Questions