Search code examples
rggplot2geom-bar

How to add multiple legend when we use multiple geom_bar?


Here is my data t

       time_granularity     N   V2    V3    V4
 1: 2019-03-07 06:00:00  3445  874  1560  2569
 2: 2019-03-07 06:15:00  5871 1366  2550  3920
 3: 2019-03-07 06:30:00  9790 2157  3831  5615
 4: 2019-03-07 06:45:00 13809 3182  5497  8055
 5: 2019-03-07 07:00:00 18559 4538  8400 11707
 6: 2019-03-07 07:15:00 23563 6015 11256 15620
 7: 2019-03-07 07:30:00 28251 7103 14380 19366
 8: 2019-03-07 07:45:00 30879 7282 15784 20503
 9: 2019-03-07 08:00:00 29575 6968 14208 18269
10: 2019-03-07 08:15:00 26898 5543 11185 14575

Here is the code

p <- ggplot(t, aes(x=time_granularity)) + 
  geom_bar(aes(y=N), alpha = 1,stat = "identity", fill='lightblue', color='lightblue4') +
  geom_bar(aes(y=V4),  alpha = 1,stat = "identity", fill="seagreen2", color='forestgreen') +
  geom_bar(aes(y=V3),  alpha = 1,stat = "identity", fill='yellow1', color='lightyellow4') +
  geom_bar(aes(y=V2),  alpha = 1,stat = "identity", fill='pink', color='red') +
  lims(y = c(0, 32000)) +
  scale_x_datetime( 
    date_breaks = "1 hour",
    date_labels = "%H:00")+
  xlab("")  +
  ylab("Count")

I want know how to add the legend and title in this code.I've tried several methods but none of them worked.It would be nice to make a change in my code. enter image description here


Solution

  • If you want a legend you have to map on aesthetics, i.e. move color=... and fill = ... into aes() and make use of scale_color/fill_manual to set your desired colors. This will automatically add a legend to your plot. Actually you get two, one for color, one for fill. These two legends can be merged into one by giving both the same title via e.g. labs. Additionally you could add a title to your plot via labs as well. BTW: I replaced geom_bar(stat="identity") with the more concise geom_col():

    library(ggplot2)
    
    ggplot(t, aes(x=time_granularity)) + 
      geom_col(aes(y=N, fill = "N", color = "N")) +
      geom_col(aes(y=V4, fill = "V4", color = "V4")) +
      geom_col(aes(y=V3, fill = "V3", color = "V3")) +
      geom_col(aes(y=V2, fill = "V2", color = "V2")) +
      scale_fill_manual(values = c(N = "lightblue", V4 = "seagreen2", V3 = "yellow1", V2 = "pink")) +
      scale_color_manual(values = c(N = "lightblue4", V4 = "forestgreen", V3 = "lightyellow4", V2 = "red")) +
      lims(y = c(0, 32000)) +
      scale_x_datetime( 
        date_breaks = "1 hour",
        date_labels = "%H:00") +
      labs(x = NULL, y = "Count", title = "My fancy title", fill = "My fancy legend", color = "My fancy legend")
    

    A second approach to achieve your desired result is to reshape your dataset into long or tidy data format using e.g. tidyr::pivot_longer and some data wrangling using dplyr. Doing so allows to make your plot with only one geom_col:

    library(tidyr)
    library(dplyr)
    
    t %>% 
      pivot_longer(-time_granularity, names_to = "var", values_to = "value") %>% 
      mutate(var = factor(var, levels = c("N", "V4", "V3", "V2"))) %>% 
      arrange(var) %>% 
      ggplot(aes(x = time_granularity, y = value, fill = var, color = var)) +
      geom_col(position = "identity") +
      scale_fill_manual(values = c(N = "lightblue", V4 = "seagreen2", V3 = "yellow1", V2 = "pink")) +
      scale_color_manual(values = c(N = "lightblue4", V4 = "forestgreen", V3 = "lightyellow4", V2 = "red")) +
      lims(y = c(0, 32000)) +
      scale_x_datetime(
        date_breaks = "1 hour",
        date_labels = "%H:00"
      ) +
      labs(x = NULL, y = "Count", title = "My fancy title", fill = "My fancy legend")