Search code examples
rggplot2legendscatter-plot

Adding legend to ggplot + putting two scatter-plots onto one graph


I have been trying to add a legend and amend it, however after spending hours on different websites, books, etc. I was unable to do it.

Data used to produce below graphs -> https://1drv.ms/u/s!Ao8fi7Xi8BskhKkDRQUn2zSdcgxofw?e=ki2eaA

library(tidyverse)
library(readr)
library(ggplot2)
library(ggpubr)
library(gridExtra)
library(cowplot)
ggplot(data = StandardCM1, aes_string(x = 'NitriteCon', y = "Absorbance")) +
    geom_smooth(method="lm", se=FALSE, aes(color = "red"), formula = y ~ x) +
        geom_point(shape = 21, size = 3, colour = "blue", fill = "blue")+
  theme(legend.position = "right")+
  scale_alpha_manual(name = NULL,
                        values = c("Standard Curve plot" = "white", "Circles" = "blue"),
                        breaks = c("Standard Curve Mean Values", "Regression Line"),
                        guide = guide_legend(override.aes = list(
                                                                  shape = c(21, NA),
                                                                  color = "blue") ) )+
  scale_y_continuous(breaks = c(0,0.05, 0.10, 0.15, 0.20, 0.25, 0.30))+
  scale_x_continuous(breaks = c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100))+
     stat_cor(label.y = 0.30, 
           aes(label = paste(..rr.label.., ..p.label.., sep = "~`,`~")))+
   stat_regline_equation(label.x=0, label.y=0.28)+
    ggtitle("Standard Curve") +
    xlab("Nitrite Concentration (µM)")+
    ylab("Absorbance")

The output of the above codes is here

As you can see, after being specific to the R, it produces a strange legend that does not reflect the thing I would like to explain. I know that in the geom_smooth(method="lm", se=FALSE, aes(color = "red"), formula = y ~ x) section - I could change aes(color = "red") onto aes(alpha = "Fitted" , however it does produce no legend at all. The examples I saw on the different forums and in the books reflected the data presented on the graph. So if there were dots, lines, triangles, whatever, these same shapes were shown within the legend. However, in my scenario (even though I could produce some kind of legend), it did not reflect the shapes presented in the graph.

Also, due to the nature of my data and its similarity, I wanted to put two scatterplots into one graph. Unfortunately, while I tried, I was utterly unsuccessful.

This is the second graph using the same data.

library(tidyverse)
library(readr)
library(ggplot2)
library(ggpubr)
library(gridExtra)
library(cowplot)
ggplot(data = StandardCM1, aes_string(x = 'NitriteCon', y = "Absorbance1")) +
    geom_smooth(method="lm", se=FALSE, aes(color = "red"), formula = y ~ x) +
        geom_point(shape = 21, size = 3, colour = "blue", fill = "blue")+
  scale_y_continuous(breaks = c(0,0.05, 0.10, 0.15, 0.20, 0.25, 0.30))+
  scale_x_continuous(breaks = c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100))+
     stat_cor(label.y = 0.30, 
           aes(label = paste(..rr.label.., ..p.label.., sep = "~`,`~")))+
   stat_regline_equation(label.x=0, label.y=0.28)+
    ggtitle("Standard Curve") +
    xlab("Nitrite Concentration (µM)")+
    ylab("Absorbance")

The output of the above codes is here

And as you have noticed, even though I have added

theme(legend.position = "right") +
  scale_alpha_manual(
    name = NULL,
    values = c("Standard Curve plot" = "white", "Circles" = "blue"),
    breaks = c("Standard Curve Mean Values", "Regression Line"),
    guide = guide_legend(
      override.aes = list(shape = c(21, NA),color = "blue"))
  )

section, R decided not to see it and produced the same legend as on the first graph. I do not get that. I know there must be some missing codes, or they are wrong, but I can't find them because R does not even tell me what is wrong. It seems it just dismissed 'pointless' values or something.

Thank you so much for your time and any potential help.

EDIT Cazman, thank you so much for your great answer; it helped me a lot. However, by saying in my title "Putting two scatter-plot onto one graph", I meant this. Therefore, I have installed the library(cowplot) and library(gridExtra), which are supposed to allow me to put multiply scatter plots (and not only) on the same page.

I know that cowplot and gridExtra are extensions of the ggplots2 and allow us to put multiply graphs of any kind that come from the ggplo2 function. But in my scenario, again, the R does not see my inputs. After adding

plot_grid(df1, df2, labels=c("A", "B"), ncol = 2, nrow = 1) 

Under this section:

ggplot(data = df,
    aes(x = NitriteConc,
        y = Absorbance)) +

It produces the following error Here

Thank you once again. I do really appreciate it.


Solution

  • My assumption from your title is that you want to combine the 2 standard curves on a single plot, and have a legend that reflects each of the curves. ggplot() created legends from the aesthetics that are passed to the aes() function. To have a legend for say, color, you first need to combine the data into a single data frame with a grouping variable (set in example below).

    df1 <- tribble(
      ~NitriteConc, ~Absorbance,
      100, 0.244288,
      50, 0.125,
      25, 0.0638,
      12.5, 0.034,
      6.25, 0.0166,
      3.13, 0.0092,
      1.56, 0.005967,
      0, 0
    )
    
    df2 <- tribble(
      ~NitriteConc, ~Absorbance,
      100, 0.25,
      50, 0.16,
      25, 0.07,
      12.5, 0.03,
      6.25, 0.02,
      3.13, 0.009,
      1.56, 0.006,
      0, 0
    )
    
    df <- df1 %>%
      mutate(set = factor(1)) %>%
      rbind(df2 %>%
              mutate(set = factor(2))) 
    

    Then setting color = set inside aes() will map a new color for each level of set. You can the set the title, labels, colors, etc. to whatever you want for each group.

    ggplot(data = df,
           aes(x = NitriteConc,
               y = Absorbance)) +
      geom_point(aes(color = set)) +
      scale_y_continuous(breaks = c(0,0.05, 0.10, 0.15, 0.20, 0.25, 0.30)) +
      scale_x_continuous(breaks = c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)) +
      scale_color_manual(values = c("blue", "red"),
                         labels = c("STD 1", "STD 2")) +
      geom_smooth(aes(color = set),
                  method = "lm",
                  formula = "y ~ x",
                  se = F) +
      stat_regline_equation(aes(color = set),
                            show.legend = FALSE) +
      stat_cor(aes(color = set),
               label.y = c(0.30, 0.28),
               show.legend = FALSE) +
      guides(color = guide_legend(title = "Curve #")) +
      labs(title = "Standard Curve") +
      xlab("Nitrite Concentration (µM)") +
      ylab("Absorbance")
    

    Which gives:

    enter image description here

    Edit: To place the scatter plots as 2 graphs in 1 chart you can use facet_wrap() like below.

    ...
      facet_wrap(~set) +
      stat_regline_equation(aes(color = set),
                            show.legend = FALSE,
                            label.y = c(0.25, 0.25)) +
      stat_cor(aes(color = set),
               label.y = c(0.23, 0.23),
               show.legend = FALSE) +
    ...
    

    enter image description here

    If you want both to have their own y axis, add scales = "free_y" to facet_wrap().

    enter image description here