0

I created a plot (with ggplot2) and now I need to add a legend. Whatever function I use it just doesn't seem to work.

I already tried with scale_fill_manual, scale_color_manual, legend.title or legend.text, etc...

My data is in a dataframe and looks like this:

  Date          SAF         MD
a 2018-06-04    3.42362418  120.00
b 2018-06-05    0.44019347  15.22
c 2018-06-06    0.20207786  6.89
d 2018-06-07    0.81154034  29.54
e 2018-06-08    0.05057167  1.48
f 2018-06-09    0.03542385  1.19
p <- ggplot(data=c,aes(x=date))+ 
  geom_point(aes(y=MD*15/440),stat='identity', group=1, col='blue',
             size=2.5, shape=21)+     
  geom_line(aes(y=MD*15/440), stat='identity',group=1, 
            color='blue')+
  geom_point(aes(y=SAF),group=1, col='orange', size=1.5)+ 
  geom_line(aes(y=SAF), stat='identity', group=1, 
            color='orange')+ 
  scale_y_continuous(name = 'SAF', sec.axis = sec_axis(~.*440/15, name = 'MD'), limits = c(0,15))+
  ggtitle('MD and SAF')+ 
  scale_x_date(date_labels = '%e %b %y', date_breaks='1 week')+ 
  theme(axis.text.x = element_text(angle=90))

There isnt any error message in particular, I can see the plot but the legend does not appear.

ronron
  • 1
  • 3
  • 1
    It doesn't have anything to do with the secondary axis. You get a legend if you assign color (or fill, linetype, etc) dynamically, i.e. inside `aes`. That's how `ggplot` works. We can't test your code since we don't have your data, but I'd guess you don't actually need to be calling `geom_point` and `geom_line` twice—you should reshape your data to fit the `ggplot` paradigm properly – camille May 15 '19 at 13:13
  • 1
    If you post something that allows us to reproduce your data as @camille wrote, then we can help better. I'm just getting started as an answerer, but imagine you're in our position: It's far, far easier to just re-create your data, tinker a bit, and say "Here, this works, and here's specifically what I did differently that made it work." – Benjamin May 15 '19 at 13:19
  • Probably a dupe of https://stackoverflow.com/q/10349206/5325862, but don't know for sure without seeing data – camille May 15 '19 at 13:21
  • I added parts of my data. @camille I tried the solution from the post you linked - the solution where data isn't melted and where you assign a constant string to the color aesthetic. Then the error is that my str is not a valid color – ronron May 15 '19 at 14:17
  • Unless there's some pressing reason why you can't reshape your data, you probably should. It's how ggplot is intended to work. I don't know what you mean by the colors being invalid. – camille May 15 '19 at 14:24
  • Also, `c` is a function, probably one that you don't want to lose access to, so it's not a good idea to name your data frame that. – camille May 15 '19 at 14:25
  • (Last comment) Is it totally necessary to have two axes for the two series, rather than putting them on one axis together? It's generally not a good way to show data legibly and accurately, so much so that the ggplot authors refused to implement it until only very recently, and intentionally put limits on what you can do with the secondary axis. – camille May 15 '19 at 14:31
  • The reason for not reshaping data so far is because I dont understand how/why (im an absolute beginner here). What I meant was, when I use `aes(colour='SAF')`and then `scale_colour_manual`, the error i get is 'invalid color name 'SAF' '. And yes the two axis are necessary because of different scale and unit. – ronron May 15 '19 at 14:46
  • Inside `aes()` you need to refer to variables (column names) of your data.frame without quotes (e.g. `aes(color=SAF)`). To use strings (e.g. `'SAF'` - with quotes) you need to use `aes_string(color='SAF')`. – Simon May 15 '19 at 16:35
  • However, in your original data.frame this wouldn't help as the variable `SAF` does not distinguish values that you want to depict in different colors. Instead, you need to put all the values you want to display on the y-axis into one variable and then use another variable (factor) to indicate their identity (factor level). `ggplot()` can use this to assign different colors to different values and also to create a legend. Please see my answer below. Does this do want you intend? – Simon May 15 '19 at 16:36

1 Answers1

0

I think you need to adjust your data frame to represent SAFand MD factor levels:

d <- rbind(data.frame(date=c$Date, SAF=c$SAF, myfactor='SAF'), data.frame(date=c$Date, SAF=c$MD, myfactor='MD'))
p <- ggplot(data=d,aes(x=date))+ 
  geom_point(aes(y=SAF*15/440, color=myfactor, shape=myfactor), data=d[d$myfactor=='MD', ])+
  geom_line(aes(y=SAF*15/440, color=myfactor), data=d[d$myfactor=='MD', ])+

  geom_point(aes(y=SAF, color=myfactor, shape=myfactor), data=d[d$myfactor=='SAF', ])+
  geom_line(aes(y=SAF, color=myfactor), data=d[d$myfactor=='SAF', ])+


  scale_y_continuous(name = 'SAF', sec.axis = sec_axis(~.*440/15, name = 'MD'), limits = c(0,15))+
  ggtitle('MD and SAF')+ 
  scale_x_date(date_labels = '%e %b %y', date_breaks='1 week')+ 
  scale_color_manual(values=c(SAF='orange', MD='blue'))+ 
  scale_shape_manual(values=c(SAF=21, MD=20))+ 
  scale_size_manual(values=c(SAF=1.5, MD=2.5))+ 
  theme(axis.text.x = element_text(angle=90))

p

enter image description here

Simon
  • 577
  • 3
  • 9