3

I have following multi-layered plot:

df <- data.frame(number = 1:10, 
                 values = rnorm(10), 
                 decision = factor(rbinom(10,1,.5), levels = c(0,1),
                                   labels=c("No","Yes")),
                 expValues = rnorm(10),
                 bandwidth = runif(10, 0,1))

ggplot(df,aes(x = number, y = values, color=decision)) + aes(group=NA) +
  geom_line(size = 1) + 
  geom_point(size = 3,shape = 16) + 
  geom_smooth(data = df, aes(ymin = values-bandwidth , ymax = values+bandwidth), 
              stat = "identity") +
  geom_point(data=df,
             aes(x=number,y=expValues),shape = "x", size = 5, color = "blue") +
  geom_text(data = data.frame(x = Inf, y = max(df$values), label = "Mean  = 12"), 
            aes(label=label, x =  x, y = y) ,
            hjust = 1, vjust = -0.1, color = "brown", size = 10) +
  geom_hline(yintercept=mean(df$values) ,color="blue", linetype = "dashed") +
  theme(text=element_text(size=20))

enter image description here

I want to add legends for geom_hline and geom_point with shape "x", denoting the for the first it is "Cut Value", for the second "Expected Value".

How can I do that?

Note: I checked THIS post and THIS post for possible solutions but cannot figure out how can I do it for especially geom_hline.

HBat
  • 4,873
  • 4
  • 39
  • 56
  • http://docs.ggplot2.org/current/guides.html – N8TRO Oct 19 '14 at 03:37
  • @N8TRO I understand from the page that one can add legends to different scales within main `data.frame` used in `ggplot()`. But it is not obvious from the page you linked how to do it for, for example `geom_hline()`. Can you kindly share your insights with a bit more detail? – HBat Oct 19 '14 at 14:40

1 Answers1

5

To add legends, the first thing to do is to actually map something to the desired aesthetic. For example, right now you've set the point shape as x, but you didn't map it inside of aes so you don't get a legend. You can map to constants as well as to variables to force a legend.

For your geom_point layer, you can just move shape inside aes, mapped to whatever constant you like. Using some value that indicates what it is will make the legend editing easier.

geom_point(data=df, aes(x=number, y=expValues, shape = "Expected value"), size = 5, color = "blue")

For the geom_hline, you'll need a dataset specific to the layer for mapping purposes. Depending on the route you go, you may also need to set show_guide to TRUE in this layer.

geom_hline(data = data.frame(yint = mean(df$values)), aes(...), show_guide = TRUE)

You could make two separate legends. You could also combine the line and shapes into a single legend as in this answer here. Both options will involve setting values in the appropriate scale_xxx_manual and using override.aes in guide_legend.

Here is how you could make a single new legend. Notice I had to add geom_hline before geom_line to make the decision legend look right.

ggplot(df, aes(x = number, y = values, color=decision, group = NA)) +
    geom_hline(data = data.frame(yint = mean(df$values)),
        aes(yintercept = yint, shape = "Cut value"), 
             color="blue", linetype = 2, show_guide = TRUE) +
    geom_line(size = 1) + 
    geom_point(size = 3,shape = 16) + 
    geom_smooth(data = df, aes(ymin = values-bandwidth , ymax = values+bandwidth), 
              stat = "identity") +
    geom_point(data=df, aes(x=number, y=expValues, shape = "Expected value"), 
             size = 5, color = "blue") +
    geom_text(data = data.frame(x = Inf, y = max(df$values), label = "Mean  = 12"), 
        aes(label=label, x =  x, y = y),
        hjust = 1, vjust = -0.1, color = "brown", size = 10) +      
    theme(text=element_text(size=20)) +
    scale_shape_manual(name = "", values = c("x", "x")) +
    guides(shape = guide_legend(override.aes = list(linetype = c(2, 0), 
                                            shape = c(NA, "x"))))

Edit Add a legend for the error band ribbon

I couldn't quite get things working with fill to add a third legend based on the error band ribbon. You could do this as three separate legends, although I don't think the spacing is as nice:

ggplot(df, aes(x = number, y = values, color=decision, group = NA)) +
    geom_hline(data = data.frame(yint = mean(df$values)),
        aes(yintercept = yint, linetype = "Cut value"), 
             color="blue", show_guide = TRUE) +
    geom_line(size = 1) + 
    geom_point(size = 3,shape = 16) + 
    geom_smooth(data = df, aes(ymin = values-bandwidth , ymax = values+bandwidth, fill = "Error band"), 
              stat = "identity") +
    geom_point(data=df, aes(x=number, y=expValues, shape = "Expected value"), 
             size = 5, color = "blue") +
    geom_text(data = data.frame(x = Inf, y = max(df$values), label = "Mean  = 12"), 
        aes(label=label, x =  x, y = y),
        hjust = 1, vjust = -0.1, color = "brown", size = 10) +  
    theme(text=element_text(size=20)) +
    scale_shape_manual(name = "", values = "x") +
    scale_linetype_manual(name = "", values = 2) +
    scale_fill_manual(name = "", values = "grey") +
    guides(shape = guide_legend(override.aes = list(linetype = 0)),
          fill = guide_legend(override.aes = list(linetype = 0)),
          color = guide_legend(override.aes = list(fill = NA)))

Alternatively, with some work inside override.aes, this could be done with the combination of colour and size along with linetype and shape.

ggplot(df, aes(x = number, y = values, color=decision, group = NA)) +
    geom_hline(data = data.frame(yint = mean(df$values)),
        aes(yintercept = yint, shape = "Cut value"), 
             color="blue", linetype = 2, show_guide = TRUE) +
    geom_line(size = 1) + 
    geom_point(size = 3,shape = 16) + 
    geom_smooth(data = df, aes(ymin = values-bandwidth , ymax = values+bandwidth, shape = "Error band"), 
              stat = "identity", show_guide = FALSE) +
    geom_point(data=df, aes(x=number, y=expValues, shape = "Expected value"), 
             size = 5, color = "blue") +
    geom_text(data = data.frame(x = Inf, y = max(df$values), label = "Mean  = 12"), 
        aes(label=label, x =  x, y = y),
        hjust = 1, vjust = -0.1, color = "brown", size = 10) +  
    theme(text=element_text(size=20)) +
    scale_shape_manual(name = "", values = rep("x", 3)) +
    guides(shape = guide_legend(override.aes = list(linetype = c(2, 1, 0), 
                                           size = c(.5, 10, 5),
                                           shape = c(NA, NA, "x"),
                                           colour = c("blue", "grey75", "blue"))))
Community
  • 1
  • 1
aosmith
  • 34,856
  • 9
  • 84
  • 118
  • I thought I should write `linetype` within `aes` in `geom_hline`. Also for the last line, `override.aes`, I thought there should be three elements in the list, additional one for `decision`. Very nice solution, thank you. By any chance, is there a possibility to write "Error Band" for the explanation for `geom_smooth`? – HBat Oct 20 '14 at 18:13
  • @HBat I couldn't seem to quite get `fill` added correctly to a single shape legend (which is needed to show the Error Band). You can either be tricky in `override.aes` with the a `size`/`linetype`/`colour` combo or add three separate legends. I've edited to demonstrate. – aosmith Oct 20 '14 at 22:25