Search code examples
rggplot2legendgeom-bargeom-point

How to show legend in a plot with both bars and points?


I have a dataframe the looks as follows:

  COUNTRY YEAR   y
     AT 2019    25
     AT 2020    38.0
     AT 2021    23.4
     BE 2019    11.1
     BE 2020    18.6
     BE 2021    15.0
     DK 2019    31.1
     DK 2020    43.6
     DK 2021    42.0

I am plotting it using both bars (year = 2021) and dots (year = 2015, 2019). I have some issues in getting the legend properly showing the right symbols. I indeed get the following graph bar and points graph

This is the final version of the code I am using:

countries <- c("AT", "BE", "DK")
years <- c(2019, 2020, 2021)
values <- c(25, 38.0, 23.4, 11.1, 18.6, 15.0, 31.1, 43.6, 42.0)

df <- data.frame(
  COUNTRY  = rep(countries, each = 3),
  YEAR = rep(years, times = 3),
  y = values
)
ggplot(df, aes(x = COUNTRY, y = y, group = YEAR, shape = as.factor(YEAR))) +
      geom_bar(data = subset(df, YEAR == 2021), aes(fill = "2021"), stat = 'identity', position = 'dodge', alpha = 0.7) +
      geom_point(data = subset(df, YEAR == 2020), aes(fill = "2020"), position = position_dodge(width = 0.4), size = 3, shape = 19, color = "red") +
      geom_point(data = subset(df, YEAR == 2019), aes(fill = "2019"), position = position_dodge(width = 0.4), size = 3, shape = 4, color = "blue") +
      scale_fill_manual(values = c("2021" = "grey", "2020" = "red", "2019" = "blue")) +
      labs(x = "Country", y = "y", fill = "") +
      theme_minimal() +
      theme(legend.position = "right")

I would like the legend to just show a "bar"/filled box for YEAR = 2021, and the two different shapes for the years 2020 and 2019 respectively.


Solution

  • Here is one option to achieve your desired result which properly maps on aesthetics instead of setting colors and shapes as arguments in geom_point and takes care that all three legends (fill, color and shape) get merged. Finally I use the override.aes argument of guide_legend to remove the fill colors for the points in the legend.

    library(ggplot2)
    
    ggplot(df, aes(x = COUNTRY, y = y, group = YEAR, shape = factor(YEAR))) +
      geom_col(
        data = subset(df, YEAR == 2021), aes(fill = factor(YEAR)),
        position = "dodge", alpha = 0.7
      ) +
      geom_point(
        data = subset(df, YEAR %in% 2019:2020),
        aes(color = factor(YEAR)),
        position = position_dodge(width = 0.4), size = 3
      ) +
      scale_fill_manual(
        values = c("2021" = "grey", "2020" = "red", "2019" = "blue"),
        aesthetics = c("color", "fill")
      ) +
      scale_shape_manual(
        values = c("2020" = 19, "2019" = 4, "2021" = NA),
      ) +
      labs(x = "Country", y = "y", fill = NULL, color = NULL, shape = NULL) +
      theme_minimal() +
      theme(legend.position = "right") +
      guides(
        fill = guide_legend(override.aes = list(fill = c(NA, NA, "grey")))
      )
    

    enter image description here