Search code examples
rggplot2bar-chartlegendtrendline

Creating Separate Legend for Specific Line in ggplot2


I'm working on a data visualization project in R using the ggplot2 package. I have a bar plot with two bars per year and a trend line that applies to one of the bars. I'm trying to create a clear legend for the plot. Currently, both bars have a dashed line in the legend instead of just one, and the legend entries are colored squares with the dashed line.

Here's the code I have so far:

# Creating a data frame
year <- c(2013:2022)
procent <- c(80, 75, 70, 65, 60, 55, 60, 50, 55, 50)
group <- "GroupA" 
DataA <- data.frame(Year = year, Procent = procent, Group = group)

year <- c(2013:2022)
procent <- c(20, 25, 30, 35, 40, 45, 40, 50, 45, 50)
group <- "GroupB"
DataB <- data.frame(Year = year, Procent = procent, Group = group)

Data <- rbind(DataA,DataB)

# Plotting the data
ggkrs <- ggplot(data = Data, aes(x = Year, y = Procent, fill = Group)) + 
  geom_bar(stat = "identity", position = "dodge", width = 0.6, size = 0.1) +
  geom_smooth(data = . %>% filter(Group == "GroupB"), method = lm, aes(x = Year, y = Procent), se = FALSE, linetype = "dashed", color = "red") +
  labs(title = "Development of Buyer Flows") +
  scale_fill_manual(values = c("GroupA" = "blue", "GroupB" = "green")) +
  scale_x_continuous(breaks = seq(min(year), max(year), by = 1)) +
  scale_y_continuous(breaks = seq(0, 100, by = 10), limits = c(0, 90)) +
  scale_linetype_manual(values = c("dashed"), name = "Trendline") +
  theme_minimal() +
  theme(legend.position = "bottom", legend.title = element_blank())

print(ggkrs)

I've tried different approaches, including separating the data for the trend line and using scale_linetype_manual(), but I haven't been able to achieve the desired result.

I've seen similar legends in Excel, where a separate legend entry for a specific line is shown. Is there a way to achieve this in ggplot2? Any guidance or examples would be greatly appreciated.

Thank you in advance for your help!


Solution

  • One potential option is to move color into your aes() for geom_smooth(). You can then name the trendline legend entry whatever you like, e.g.

    library(tidyverse)
    
    # Creating a data frame
    year <- c(2013:2022)
    procent <- c(80, 75, 70, 65, 60, 55, 60, 50, 55, 50)
    group <- "GroupA" 
    DataA <- data.frame(Year = year, Procent = procent, Group = group)
    
    year <- c(2013:2022)
    procent <- c(20, 25, 30, 35, 40, 45, 40, 50, 45, 50)
    group <- "GroupB"
    DataB <- data.frame(Year = year, Procent = procent, Group = group)
    
    Data <- rbind(DataA,DataB)
    
    # Plotting the data
    ggkrs <- ggplot(data = Data, aes(x = Year, y = Procent, fill = Group)) + 
      geom_bar(stat = "identity", position = "dodge", width = 0.6, size = 0.1) +
      geom_smooth(data = . %>% filter(Group == "GroupB"), 
                  method = lm, aes(x = Year, y = Procent, color = "trendline of Procent per Year"), 
                  se = FALSE, linetype = "dashed", inherit.aes = FALSE) +
      labs(title = "Development of Buyer Flows") +
      scale_fill_manual(values = c("GroupA" = "blue", "GroupB" = "green")) +
      scale_x_continuous(breaks = seq(min(year), max(year), by = 1)) +
      scale_y_continuous(breaks = seq(0, 100, by = 10), limits = c(0, 90)) +
      scale_linetype_manual(values = c("dashed"), name = "Trendline") +
      theme_minimal() +
      theme(legend.position = "bottom", legend.title = element_blank())
    #> Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
    #> ℹ Please use `linewidth` instead.
    #> This warning is displayed once every 8 hours.
    #> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
    #> generated.
    
    print(ggkrs)
    #> `geom_smooth()` using formula = 'y ~ x'
    

    Created on 2023-08-30 with reprex v2.0.2