Search code examples
rggplot2legend

Add label item to legend similar to geom_label_repel()


I have a plot of species richness that has nine lines. I have labelled each line at the end using geom_label_repel() with the appropriate quadrate number. I want to add in my legend a similar black label box with a number 1 or a hash (#) in it with 'Quadrat Number' written next to it.

This is my current plot:

enter image description here

This an edited version in powerpoint that id like the legend to look like:

enter image description here

Subset of data:

data for plot (index):

structure(c("function (..., list = character(), package = NULL, lib.loc = NULL, ", 
"    verbose = getOption(\"verbose\"), envir = .GlobalEnv, overwrite = TRUE) ", 
"{", "    fileExt <- function(x) {", "        db <- grepl(\"\\\\.[^.]+\\\\.(gz|bz2|xz)$\", x)", 
"        ans <- sub(\".*\\\\.\", \"\", x)"), dim = c(6L, 1L), dimnames = list(
    c("1", "2", "3", "4", "5", "6"), ""), class = "noquote")

labels for plot (labels_df):

structure(list(Quadrat = structure(1:9, levels = c("1", "2", 
"3", "4", "5", "6", "7", "8", "9"), class = "factor"), Year = c(2024L, 
2024L, 2024L, 2024L, 2024L, 2024L, 2024L, 2024L, 2024L), ID = c("1_24", 
"2_24", "3_24", "4_24", "5_24", "6_24", "7_24", "8_24", "9_24"
), Source = c("Beaver", "Beaver", "Beaver", "Beaver", "Beaver", 
"Beaver", "SSSI", "SSSI", "SSSI"), specNum = c(20L, 21L, 19L, 
6L, 2L, 8L, 15L, 29L, 16L), simpson = c(0.95, 0.952380952380952, 
0.947368421052632, 0.833333333333333, 0.5, 0.875, 0.933333333333333, 
0.96551724137931, 0.9375), shannon = c(2.99573227355399, 3.04452243772342, 
2.94443897916644, 1.79175946922805, 0.693147180559945, 2.07944154167984, 
2.70805020110221, 3.36729582998647, 2.77258872223978), H = c(2.99573227355399, 
3.04452243772342, 2.94443897916644, 1.79175946922805, 0.693147180559945, 
2.07944154167984, 2.70805020110221, 3.36729582998647, 2.77258872223978
), fisher = c(4294967306, 4294967306.5, 4294967305.5, 1073741869.66667, 
268435505.000009, 2147483652, 4294967303.5, 4294967310.5, 4294967304
)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-9L))

Code for plot

library(ggplot2)            # for plottin graphs
library(ggrepel)            # for geom_label_repel()
library(pals)               # for lines colour scale

specPlot <- ggplot(index, aes(x=Year, y=specNum, group=Quadrat, color=Quadrat, linetype=Source)) +
  geom_line() +
  geom_point() +
  labs(x='Year', y='Species Richness') +
  scale_colour_manual(values = unname(kovesi.isoluminant_cgo_70_c39(n=9)), guide = "none") +
  scale_linetype_manual(name = NULL, values = c('Beaver' = 'solid', 'SSSI' = 'dashed')) +
  geom_label_repel(data=labels_df,aes(label=Quadrat),
                   direction='y',
                   segment.colour='black',
                   xlim=c(2024,2025),
                   na.rm = TRUE,
                   max.overlaps=100,
                   show.legend = FALSE) +
  theme_classic() +
  theme(legend.position='top',
        legend.direction = 'horizontal',
        text = element_text(size = 14, family = 'Calibri Light')) +
  coord_cartesian(clip='off')

Solution

  • Here is one option to achieve your desired result which fakes a legend for the "label" by mapping on the alpha aes and setting show.legend=TRUE. However, this requires some additional tweaking via the override.aes argument to get your desired symbol.

    Unfortunately this will display the label in the linetype legend too and the only option I have found to get rid of this was to use the override.aes argument a second time.

    library(ggplot2) # for plottin graphs
    library(ggrepel) # for geom_label_repel()
    library(pals) # for lines colour scale
    
    set.seed(123)
    
    ggplot(index, aes(x = Year, y = specNum, color = Quadrat)) +
      geom_line(aes(linetype = Source, group = Quadrat)) +
      geom_point() +
      labs(x = "Year", y = "Species Richness") +
      scale_colour_manual(values = unname(kovesi.isoluminant_cgo_70_c39(n = 9)), guide = "none") +
      scale_linetype_manual(
        name = NULL, values = c("Beaver" = "solid", "SSSI" = "dashed")
      ) +
      scale_alpha_manual(
        name = NULL, values = 1
      ) +
      geom_label_repel(
        data = subset(index, Year >= max(Year)),
        aes(
          label = Quadrat,
          alpha = "Quadrat Number"
        ),
        direction = "y",
        segment.colour = "black",
        xlim = c(2024, 2025),
        na.rm = TRUE,
        max.overlaps = 100
      ) +
      theme_classic() +
      theme(
        legend.position = "top",
        legend.direction = "horizontal",
        #text = element_text(size = 14, family = "Calibri Light")
      ) +
      coord_cartesian(clip = "off") +
      guides(
        alpha = guide_legend(override.aes = list(label = "#")),
        linetype = guide_legend(override.aes = list(label = "", fill = NA, size = 0))
      )
    #> `geom_line()`: Each group consists of only one observation.
    #> ℹ Do you need to adjust the group aesthetic?