Brennan
Brennan

Reputation: 429

Adding a legend to a ggplot that combines geom_line and geom_shape using R

I have the following MWE:

library(scales)
library(tidyverse)

Canada <- c(383.927, 387.088, 390.648, 393.926, 395.947, 393.98, 388.772, 
392.391, 391.804, 389.321, 390.583, 390.062, 390.596, 392.19, 
392.267, 397.572, 397.807, 394.64, 391.737, 392.659, 392.483, 
392.012, 391.842, 394.06, 391.661, 390.621, 392.533, 396.218, 
401.802, 397.298, 392.468, 392.056, 394.752, 392.947, 392.606, 
391.839, 392.169, 393.29, 399.993, 396.114, 403.1, 398.263, 395.066, 
397.16, 399.562, 396.865, 392.898, 396.89, 398.529, 402.269, 
-9.999e+09, 398.294, 401.033, 399.328, -9.999e+09, 400.062, 395.829, 
397.754, 395.306, 394.87, 398.469, 399.91, 405.053, 404.678, 
402.185, 396.605, -9.999e+09, 402.252, 405.295, 401.08, 400.527, 
398.38, 400.152, 396.42, 402.497, 406.855, 403.56, -9.999e+09, 
-9.999e+09, 405.773, 402.306, 403.146, 403.079, 400.712)

Canada1 <- c(390.704083333333, 393.322083333333, 393.900083333333, 396.780833333333, 
398.3274, 401.312181818182, 402.45)

x.axis <- c("Jan. 2010","","","","","July 2010","","","","","",
"Dec. 2010","","","","","","July 2011","","","","","",
"Dec. 2011","","","","","","July 2012","","","","","",
"Dec. 2012","","","","","","July 2013","","","","","",
"Dec. 2013","","","","","","July 2014","","","","","",
"Dec. 2014","","","","","","July 2015","","","","","",
"Dec. 2015","","","","","","July 2016","","","","","",
"Dec. 2016","")

# Edit
d1 <- as.Date(paste0("201001","01"), "%Y%m%d")
d2 <- as.Date(paste0("201612","01"), "%Y%m%d")
date1 <- format(seq(d1,d2,by="month"), "%Y%m%d")
datCan <- data.frame(co2 = Canada, labels = as.character(time), date = date1, group = 1)
d1 <- as.Date(paste0("201006","01"), "%Y%m%d")
d2 <- as.Date(paste0("201606","01"), "%Y%m%d")
date2 <- format(seq(d1,d2,by="year"), "%Y%m%d")
dat2Can <- data.frame(co2 = Canada1, date = date2, group = 2)

Canplot <- ggplot() + geom_line(data = datCan, aes(x = date, y = co2, group = group)) 
  + geom_line(data = dat2Can, linetype = "dashed", aes(x = date, y = co2, group = group), color = "Red")
  + geom_point(data = dat2Can, size=2, aes(x = date, y = co2, group = group), color = "Red")
  + ylim(380,410) + scale_x_discrete(labels = x.axis)
  + theme_classic(base_size=12) + ylab("yval")
  + xlab("Time") + theme(axis.text.x = element_text(angle = 45, hjust=1))

Which produces

enter image description here

I want to add a legend to this plot but am having troubles because of my inclusion of geom_line and geom_point. I believe I need to do it this way because the points are in specific locations. Any idea as to how I can do this? I am open to creating a standalone legend that is just a black line and red dashed line with a circle in the middle of it. This would work fine because I am using LaTeX to format my document anyway.

Upvotes: 0

Views: 285

Answers (1)

dc37
dc37

Reputation: 16178

To get two different legends for different dataframes, you can have the use of new_color_scale function from ggnewscale package.

Here, I used lubridate to add date sequences to your individual vectors for lines and points and then I create dataframes from those:

library(lubridate)
date_seq = seq(ymd("2010-01-01"),ymd("2016-12-01"),length.out = length(Canada))
date_seq_point = seq(ymd("2010-06-01"),ymd("2016-06-01"),length.out = length(Canada1))

Can <- data.frame(Canada = Canada,
                  Xaxis = date_seq,
                  dataset = "Lines")

Can_point = data.frame(Canada = Canada1,
                       Xaxis = date_seq_point,
                       dataset2 ="Points")

Now, you can do the plot with these new dataframes and get the appropriate legend for both lines and points when calling new_color_scale:

library(ggnewscale)
library(ggplot2)

ggplot()+
  geom_line(data = Can, aes(x = Xaxis, y = Canada, color = dataset))+
  scale_color_manual(name = "Lines",values = "black")+
  new_scale_color()+
  geom_line(data = Can_point, aes(x  = Xaxis, y = Canada, color = dataset2))+
  geom_point(data = Can_point, aes(x  = Xaxis, y = Canada, color = dataset2))+
  scale_color_manual(name = "Points",values = "red")+
  ylim(380,410)+
  scale_x_date(date_breaks = "6 months", date_labels = "%b %Y")+
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

enter image description here


EDIT: two different legends in one legends

As per OP's request, the goal is to keep one legend for Lines and Points but not having points displayed in the legend of lines.

So, you can bind together both dataframes by doing:

library(lubridate)
date_seq = seq(ymd("2010-01-01"),ymd("2016-12-01"),length.out = length(Canada))
date_seq_point = seq(ymd("2010-06-01"),ymd("2016-06-01"),length.out = length(Canada1))

Can <- data.frame(Canada = Canada,
                  Xaxis = date_seq,
                  dataset = "Lines")

Can_point = data.frame(Canada = Canada1,
                       Xaxis = date_seq_point,
                       dataset ="Points")

DF <- rbind(Can, Can_point)

Then, you can plot lines and points in function of each dataset but control shape of points by adding shape argument into aes. Then, you can set the shape of black points to be NA in scale_shape_manual:

library(ggplot2) 

ggplot(DF, aes(x = Xaxis, y = Canada, color = dataset, shape = dataset))+
  geom_point()+
  geom_line()+
  ylim(380,410)+
  scale_color_manual(values = c("black","red"))+
  scale_shape_manual(values = c(NA,16))

enter image description here

Does it answer your question ?

Upvotes: 1

Related Questions