Search code examples
rggplot2legend

ggplot manually adjusting attributes


I am trying to change the legend on this plot in ggplot. I want it to have both the appropriate linetype and color in the one legend. However, I would be satisfied if I could just fix the linetype so it is correct and forget about the different colors. The below code does everything I want expect having the correct linetype in the legend. The last line of code does not appear to do anything, but I have included it to show my best attempt so far.

library(tidyverse)

ggplot(data.frame(x = c(-3,3)), aes(x = x))+
  stat_function(fun=dnorm, aes(color="mean 2"), linetype = 1,  
                linewidth = 1.5, args = list(mean = 2))+ 
  stat_function(fun=dnorm, aes(color="mean 0"), linetype = 2,  
                linewidth = 1.5, args = list(mean = 0))+ 
  scale_color_manual(values = c("red", "blue"), 
                     name = "Mean")+ 
  scale_linetype_manual(values = c(1, 2))

Here is the plot that is produced:

enter image description here

I know how to do what I want in base R and other software but I am sticking to ggplot to be consistent with other aspects of this project. I am also aware that there are better ways to plot the normal distribution. This is a simplified version of my problem using an example that is more reproducible and more easily accessible to others in order to maximize my chances of solving me issue.

Bonus: If you know why my attempt did not work I would love to know that also!


Solution

  • The linetype also has to be in the aesthetic. The manual scales also have to be the same name.

    library(tidyverse)
    
    ggplot(data.frame(x = c(-3,3)), aes(x = x))+
      stat_function(fun=dnorm, aes(color="mean 2", linetype="mean 2"), 
                    linewidth = 1.5, args = list(mean = 2))+ 
      stat_function(fun=dnorm, aes(color="mean 0", linetype = "mean 0"), 
                    linewidth = 1.5, args = list(mean = 0))+ 
      scale_color_manual(values = c("red", "blue"), 
                         name = "Mean")+ 
      scale_linetype_manual(values = c(1, 3), name="Mean")
    

    Created on 2024-04-07 with reprex v2.0.2

    As for why your first attempt wasn't working - it actually was. The larger line-width made it appear in the legend as though the two lines were both solid, but it was actually printing one slightly shorter line. You can see how it works below with a narrower line.

    library(tidyverse)
    
    ggplot(data.frame(x = c(-3,3)), aes(x = x))+
      stat_function(fun=dnorm, aes(color="mean 2", linetype="mean 2"), 
                    linewidth = .5, args = list(mean = 2))+ 
      stat_function(fun=dnorm, aes(color="mean 0", linetype = "mean 0"), 
                    linewidth = .5, args = list(mean = 0))+ 
      scale_color_manual(values = c("red", "blue"), 
                         name = "Mean")+ 
      scale_linetype_manual(values = c(1, 2), name="Mean")
    

    Created on 2024-04-07 with reprex v2.0.2