Home > Software engineering >  How do I add a legend based to my scatterplot based on annotate("rect")?
How do I add a legend based to my scatterplot based on annotate("rect")?

Time:05-03

I have created a scatterplot using ggplot2 in RStudio with the function annotate("rect".... to add a layer of colours based on another variable. I have been trying to add a legend for SO long by googling and trying different methods found on this site and others, including using geom_rect function but I cannot seem to get it to work fully. Please can anyone help me add a legend purely based on the shaded areas. See my plot:

the plot I have made so far

This is my script so far:

ggplot(prpc_data,aes(x=age,y=total_proprioception)) 
      annotate("rect",xmin = 2, xmax = 9, ymin = -Inf, ymax = Inf, colour="blue", fill="blue",alpha = 0.15) 
      annotate("rect",xmin=6,xmax=12,ymin=-Inf,ymax=Inf,colour="hotpink",fill="hotpink",alpha=0.15) 
      annotate("rect",xmin=8,xmax=16,ymin=-Inf,ymax=Inf,colour="yellow",fill="yellow",alpha=0.2) 
      geom_point(shape=21,size=2,colour="black",fill="cadetblue3") 
      geom_smooth(method="loess",se=FALSE,colour="cadetblue") 
      labs(x="Age (years)",y="Mean proprioception score (0-4)") 
      coord_cartesian(ylim=c(0,4),xlim=c(2,16)) 
      scale_y_continuous(breaks=seq(0,4,0.5)) 
      scale_x_continuous(breaks=seq(2,16,2)) 
      theme_bw()

I would be very grateful for any help

CodePudding user response:

Annotation layers in ggplot2 are typically used for one-off labels, notes, and symbols, and don't usually relate to a legend. The easiest way to get a legend for some shaded areas would be to make those a normal geom_* layer with aethestics mapped to variables.

Below, I give the geom_rect layer its own data frame, and specific inherit.aes = FALSE so that that layer ignores the global aes(wt, mpg) assignment. Since the fill of those rectangles are mapped to the category, a legend is automatically created.

ggplot(mtcars, aes(wt, mpg))  
  geom_rect(data = data.frame(zone  = factor(c("low", "mid", "high"),
                                             levels = c("low", "mid", "high")),
                              start = c(0,3,4),
                              end   = c(3,4,6)),
            inherit.aes = FALSE,
            aes(xmin = start, xmax = end, ymin = 0, ymax = Inf, fill = zone),
            alpha = 0.1)  
  geom_point() 

enter image description here

CodePudding user response:

Instead of adding rectangles using annotate, you can use geom_rect and map its fill aesthetic to whatever labels you want. To do this you can create a little rect_df that you pass to geom_rect, and use scale_fill_manual to give the rectangles the fill colours you want:

rect_df <- data.frame(xmin = c(2, 6, 8), xmax = c(9, 12, 16),
                      labs = c("Range1", "Range2", "Range3"))

ggplot(prpc_data, aes(age, total_proprioception))  
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = -Inf, ymax = Inf, fill = labs), 
                alpha = 0.2, data = rect_df, inherit.aes = FALSE)  
      geom_point(shape = 21, size = 2, colour = "black", fill = "cadetblue3")  
      geom_smooth(method = "loess", se = FALSE, colour = "cadetblue")  
      labs(x = "Age (years)", y = "Mean proprioception score (0-4)")  
      coord_cartesian(ylim = c(0, 4), xlim = c(2, 16))  
      scale_fill_manual(values = c("blue", "hotpink", "yellow"))  
      scale_y_continuous(breaks = seq(0, 4, 0.5))  
      scale_x_continuous(breaks = seq(2, 16, 2))  
      theme_bw()

enter image description here


Data used to emulate OP plot

set.seed(1)

prpc_data <- data.frame(age = runif(50, 0, 16))
prpc_data$total_proprioception <- rnorm(50, prpc_data$age, prpc_data$age/4)^2/200
  • Related