8
votes

I keep running into this issue in ggplot2, perhaps someone can help me.

I have a plot where the order of the variables in the legend is in reverse order to how they are displayed on the plot.

For example:

df=data.frame(
 mean=runif(9,2,3),
 Cat1=rep(c("A","B","C"),3),
 Cat2=rep(c("X","Y","Z"),each=3))

dodge=position_dodge(width=1)
ggplot(df,aes(x=Cat1,y=mean,color=Cat2))+
 geom_point(aes(shape=Cat2),size=4,position=dodge)+
 scale_color_manual(values=c("red","blue","black"))+
 scale_shape_manual(values=c(16:19))+
 coord_flip()

produces:

example

So the points are displayed on the plot as Cat2=Z,Y, then X (black diamonds, blue triangle, red circle) but in the legend they are displayed as Cat2=X, Y, then Z (red circle, blue triangle, black diamond).

How can I reverse the order of the legend without shifting the points on the plot? Reordering the factor produces the opposite problem (points on the plot are reversed).

Thanks!

2
For now, probably there is no easy way. The next version may have an option to reverse the legend order, though.kohske
Hmm, that stinks. Good to know. Thanks for the heads up!jslefche
@hadley yes, yes. why did I miss it???kohske
@jslefche so you can easily modify it. sorry for the misleading.kohske
Sorry for my ignorance, do I set the breaks for scale_x_discrete("Cat2")?jslefche

2 Answers

4
votes

To flesh out Hadley's comment, we would do something like this:

ggplot(df,aes(x=Cat1,y=mean,color=Cat2))+
 geom_point(aes(shape=Cat2),size=4,position=dodge)+
 scale_color_manual(values=c("red","blue","black"),breaks = c('Z','Y','X'))+
 scale_shape_manual(values=c(16:19),breaks = c('Z','Y','X'))+
 coord_flip()

enter image description here

Note that we had to set the breaks in both scales. If we did just one, they wouldn't match, and ggplot would split them into two legends, rather than merging them.

0
votes

As far as i understand what you want to achieve, this simple manipulation does the trick for me:

  1. define a Cat2 as a factor (with the levels in the adequate order) and
  2. chage the order of colours and shapes to match the levels order (in the scale_manual commands)

Here is the code to do it:

library(ggplot2)

df=data.frame(
    mean=runif(9,2,3),
    Cat1=rep(c("A","B","C"),3),
    Cat2=factor(rep(c("X","Y","Z"),each=3), levels=c('Z', 'Y', 'X'))) 

dodge=position_dodge(width=1)
ggplot(df,aes(x=Cat1,y=mean,color=Cat2))+
    geom_point(aes(shape=Cat2),size=4,position=dodge)+
    scale_color_manual(values=c("black","blue","red"))+
    scale_shape_manual(values=c(18:16))+
    coord_flip()