4

I'm trying to plot 2 sets of data points and a single line in R using ggplot. The issue I'm having is with the legend. As can be seen in the attached image, the legend applies the lines to all 3 data sets even though only one of them is plotted with a line.

I have melted the data into one long frame, but this still requires me to filter the data sets for each individual call to geom_line() and geom_path().

I want to graph the melted data, plotting a line based on one data set, and points on the remaining two, with a complete legend.

Here is the sample script I wrote to produce the plot:

xseq <- 1:100
x <- rnorm(n = 100, mean = 0.5, sd = 2)
x2 <- rnorm(n = 100, mean = 1, sd = 0.5)
x.lm <- lm(formula = x ~ xseq)
x.fit <- predict(x.lm, newdata = data.frame(xseq = 1:100), type = "response", se.fit = TRUE)
my_data <- data.frame(x = xseq, ypoints = x, ylines = x.fit$fit, ypoints2 = x2)

## Now try and plot it
melted_data <- melt(data = my_data, id.vars = "x")

p <- ggplot(data = melted_data, aes(x = x, y = value, color = variable, shape = variable, linetype = variable)) +
  geom_point(data = filter(melted_data, variable == "ypoints")) +
  geom_point(data = filter(melted_data, variable == "ypoints2")) +
  geom_path(data = filter(melted_data, variable == "ylines"))

pushViewport(viewport(layout = grid.layout(1, 1))) # One on top of the other
print(p, vp = viewport(layout.pos.row = 1, layout.pos.col = 1))

Resulting plot from the sample code above

Lancophone
  • 310
  • 2
  • 17
  • 1
    Have you done some research? There's e.g. http://stackoverflow.com/questions/18394391/r-custom-legend-for-multiple-layer-ggplot and http://stackoverflow.com/questions/17148679/ggplot2-need-to-construct-a-manual-legend-for-complicated-plot – mts Aug 14 '15 at 11:53
  • These are not quite what I'm looking for. I don't want a split legend; I'd like a single legend as I have currently with the following changes: 1) a red line without the circle 2) a green triangle without the dashed line 3) a blue square without the dotdash line – Lancophone Aug 14 '15 at 11:59

1 Answers1

4

You can set them manually like this:

We set linetype = "solid" for the first item and "blank" for others (no line).

Similarly for first item we set no shape (NA) and for others we will set whatever shape we need (I just put 7 and 8 there for an example). See e.g. http://www.r-bloggers.com/how-to-remember-point-shape-codes-in-r/ to help you to choose correct shapes for your needs.

If you are happy with dots then you can use my_shapes = c(NA,16,16) and scale_shape_manual(...) is not needed.

my_shapes = c(NA,7,8)

ggplot(data = melted_data, aes(x = x, y = value, color=variable, shape=variable )) +
   geom_path(data = filter(melted_data, variable == "ylines") ) + 
   geom_point(data = filter(melted_data, variable %in% c("ypoints", "ypoints2"))) +
   scale_colour_manual(values =  c("red", "green", "blue"),
                       guide = guide_legend(override.aes = list(
                          linetype = c("solid", "blank","blank"),
                          shape = my_shapes))) +
   scale_shape_manual(values = my_shapes)

enter image description here

But I am very curious if there is some more automated way. Hopefully someone can post better answer.

This post relied quite heavily on this answer: ggplot2: Different legend symbols for points and lines

Community
  • 1
  • 1
Pekka
  • 2,348
  • 2
  • 21
  • 33
  • Thanks @Pekka, this is exactly what I was looking for! :-) I am also keen on hearing about potential autmoated answers. I heard somewhere that it is possible, but can't recall the source – Lancophone Aug 14 '15 at 13:10
  • Hi Pekka, this isn't quite correct, as I can't change the shape of the plot. Although the legend is correct in saying green points and blue triangles, the plot does not comploy – Lancophone Aug 14 '15 at 13:21
  • I see what you mean. Then we need to set the shapes manually as well. I edited the answer. Luckily we can define the shape vector once and use the same vector then for the legend and the plot. – Pekka Aug 14 '15 at 16:39
  • I'll remove the edit to my question in this case :-) Thanks again @Pekka – Lancophone Aug 14 '15 at 16:48