78

I'm trying to get a custom legend for a ggplot with data coming from two separate data frames. See below for a minimum reproducible example.

What I'm trying to accomplish is to have a legend describing the ribbon fill, the black line, and the red line.

require(ggplot2)
x=seq(1,10,length=100)
data=data.frame(x,dnorm(x,mean=6.5,sd=1))
names(data)=c('x','new.data')
x.ribbon=seq(1,10,length=20)
ribbon=data.frame(x.ribbon,
                  dnorm(x.ribbon,mean=5,sd=1)+.01,
                  dnorm(x.ribbon,mean=5,sd=1)-.01,
                  dnorm(x.ribbon,mean=5,sd=1))
names(ribbon)=c('x.ribbon','max','min','avg')
ggplot()+geom_ribbon(data=ribbon,aes(ymin=min,ymax=max,x=x.ribbon),fill='lightgreen')+
  geom_line(data=ribbon,aes(x=x.ribbon,y=avg),color='black')+
  geom_line(data=data,aes(x=x,y=new.data),color='red')+
  xlab('x')+ylab('density')

enter image description here

zx8754
  • 52,746
  • 12
  • 114
  • 209
scs217
  • 2,218
  • 2
  • 17
  • 18

1 Answers1

122

Instead of setting colour and fill, map them using the geometry aesthetics aes and then use scale_xxx_manual or scale_xxx_identity.

Eg

ggplot()+geom_ribbon(data=ribbon,aes(ymin=min,ymax=max,x=x.ribbon,fill='lightgreen'))+
    geom_line(data=ribbon,aes(x=x.ribbon,y=avg,color='black'))+
    geom_line(data=data,aes(x=x,y=new.data,color='red'))+
    xlab('x')+ylab('density') + 
    scale_fill_identity(name = 'the fill', guide = 'legend',labels = c('m1')) +
    scale_colour_manual(name = 'the colour', 
         values =c('black'='black','red'='red'), labels = c('c2','c1'))

enter image description here

Note that you must specify guide = 'legend' to force scale_..._identity to produce a legend.

scale_...manual you can pass a named vector for the values -- the names should be what you called the colours within the calls to geom_... and then you can label nicely.

JanLauGe
  • 2,297
  • 2
  • 16
  • 40
mnel
  • 113,303
  • 27
  • 265
  • 254
  • 27
    It took me a while to realize that I had colors set outside of the aesthetic definition. It is a subtle difference. – scs217 Aug 24 '13 at 03:42
  • 19
    +1. BTW, for further clarification, I would say: `geom_line(aes(..., color = 'a')...)` and then `scale_color_manual(..., values = c('a' = 'black', ...))`. That way it is clear that the string in `aes(color = 'string')` is just a binding, the actual color will be whatever you define in `scale_color_manual()`. – Pierre D Mar 13 '15 at 22:32
  • 3
    Thanks for this! I agree with @scs217 that the subtle difference between setting colour in `geom_line(colour = x)` vs in `geom_line(aes(colour = x))` can easily be missed. I have suggested an edit to put more emphasis on that. – JanLauGe Oct 05 '17 at 13:01