rggplot2graphr-library

R - (ggplot2 library) - Legends not showing on graphs


What I'm doing

I'm using a library for R called ggplot2, which allows for a lot of different options for creating graphics and other things. I'm using that to display two different data sets on one graph with different colours for each set of data I want to display.

The Problem

I'm also trying to get a legend to to show up in my graph that will tell the user which set of data corresponds to which colour. So far, I've not been able to get it to show.

What I've tried

I've set it to have a position at the top/bottom/left/right to make sure nothing was making it's position to none by default, which would've hidden it.

The Code

# PDF/Plot generation
pdf("activity-plot.pdf")
ggplot(data.frame("Time"=times), aes(x=Time)) +

  #Data Set 1
  geom_density(fill = "#1A3552", colour = "#4271AE", alpha = 0.8) +
  geom_text(x=mean(times)-1, y=max(density(times)$y/2), label="Mean {1} Activity", angle=90, size = 4) +
  geom_vline(aes(xintercept=mean(times)), color="cyan", linetype="dashed", size=1, alpha = 0.5) +

  # Data Set 2
  geom_density(data=data.frame("Time"=timesSec), fill = "gray", colour = "orange", alpha = 0.8) +
  geom_text(x=mean(timesSec)-1, y=max(density(timesSec)$y/2), label="Mean {2} Activity", angle=90, size = 4) +
  geom_vline(aes(xintercept=mean(timesSec)), color="orange", linetype="dashed", size=1, alpha = 0.5) + 

  # Main Graph Info
  labs(title="Activity in the past 48 hours", subtitle="From {DATE 1} to {DATE 2}", caption="{LOCATION}") +
  scale_x_continuous(name = "Time of Day", breaks=seq(c(0:23))) + 
  scale_y_continuous(name = "Activity") +
  theme(legend.position="top")

dev.off()

Result

image


Solution

  • As pointed out by @Ben, you should pass the color into an aes in order to get the legend being displayed.

    However, a better way to get a ggplot is to merge your two values "Time" and "Timesec" into a single dataframe and reshape your dataframe into a longer format. Here, to illustrate this, I created this dummy dataframe:

    Time = sample(1:24, 200, replace = TRUE)
    Timesec = sample(1:24, 200, replace = TRUE)
    df <- data.frame(Time, Timesec)
    
      Time Timesec
    1   22      23
    2   21       9
    3   19       9
    4   10       6
    5    7      24
    6   15       9
    ... ...     ...
    

    So, the first step is to reshape your dataframe into a longer format. Here, I'm using pivot_longer function from tidyr package:

    library(tidyr)
    library(dplyr)
    df %>% pivot_longer(everything(), names_to = "var",values_to = "val")
    
    # A tibble: 400 x 2
       var       val
       <chr>   <int>
     1 Time       22
     2 Timesec    23
     3 Time       21
     4 Timesec     9
     5 Time       19
     6 Timesec     9
     7 Time       10
     8 Timesec     6
     9 Time        7
    10 Timesec    24
    # … with 390 more rows
    

    To add geom_vline and geom_text based on the mean of your values, a nice way of doing it easily is to create a second dataframe gathering the mean and the maximal density values needed to be plot:

    library(tidyr)
    library(dplyr)
    df_lab <- df %>% pivot_longer(everything(), names_to = "var",values_to = "val") %>%
      group_by(var) %>%
      summarise(Mean = mean(val),
                Density = max(density(val)$y))
    
    # A tibble: 2 x 3
      var      Mean Density
      <chr>   <dbl>   <dbl>
    1 Time     11.6  0.0555
    2 Timesec  12.1  0.0517
    

    So, using df and df_lab, you can generate your entire plot. Here, we passed color and fill arguments into the aes and use scale_color_manual and scale_fill_manual to set appropriate colors:

    library(dplyr)
    library(tidyr)
    library(ggplot2)
    
    df %>% pivot_longer(everything(), names_to = "var",values_to = "val") %>%
      ggplot(aes(x = val, fill = var, colour = var))+
      geom_density(alpha = 0.8)+
      scale_color_manual(values = c("#4271AE", "orange"))+
      scale_fill_manual(values = c("#1A3552", "gray"))+
      geom_vline(inherit.aes = FALSE, data = df_lab, 
                 aes(xintercept = Mean, color = var), linetype = "dashed", size = 1,
                 show.legend = FALSE)+
      geom_text(inherit.aes = FALSE, data = df_lab,
                aes(x = Mean-0.5, y = Density/2, label = var, color = var), angle = 90, 
                show.legend = FALSE)+
      labs(title="Activity in the past 48 hours", subtitle="From {DATE 1} to {DATE 2}", caption="{LOCATION}") +
      scale_x_continuous(name = "Time of Day", breaks=seq(c(0:23))) + 
      scale_y_continuous(name = "Activity") +
      theme(legend.position="top")
    

    enter image description here

    Does it answer your question ?