Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add manual legend to ggplot that is not part of any scale?

Tags:

r

legend

ggplot2

I want to add a legend of p value significance to my plot, which is added using stat_pvalue_manual. The label is not part of any aesthetic mappings. Here is some mock code:

stat.df <- data.frame(group1 = c("setosa", "setosa"),
                      group2 = c("versicolor", "virginica"),
                      significance = c("ns", "*"), 
                      y.position = c(8,8.3))

iris %>% ggplot(aes(Species, Sepal.Length)) + 
  geom_boxplot() + 
  ggpubr::stat_pvalue_manual(stat.df, label = "significance") +
  theme_classic()

enter image description here

And I want something along the line of:

enter image description here

Is there a way to add the legend using guides or other ggplot function?

like image 399
Ian Avatar asked Sep 17 '25 23:09

Ian


1 Answers

One option would be to use guide_custom which was introduced in ggplot2 3.5.0 and allows to add a custom legend via a grob. In the code below I combine it with gridtext::richtext_grob for markdown styling:

library(ggplot2)
library(ggpubr)
library(gridtext)
library(grid)

iris |>
  ggplot(aes(Species, Sepal.Length)) +
  geom_boxplot() +
  ggpubr::stat_pvalue_manual(stat.df, label = "significance") +
  theme_classic() +
  guides(
    custom = guide_custom(
      gridtext::richtext_grob(
        paste(
          "**ns** not sigfnificant",
          "**\\*** p < 0.05",
          sep = "<br>"
        ),
        halign = 0,
        gp = grid::gpar(fontsize = 8)
      ),
      title = "Significance",
      theme = theme(
        legend.title = element_text(face = "bold")
      )
    )
  )

UPDATE Separating the legend keys and the text requires more effort. Perhaps the easiest approach would be to use a gridExtra::tableGrob. A second option would be to build the column or grid layout from scratch which I do below using the gtable package:

library(ggplot2)
library(ggpubr)
library(gridtext)
library(grid)
library(gtable)

column1 <- gridtext::richtext_grob(
  paste("ns", "*", sep = "<br>"),
  x = 0, halign = .5,
  vjust = 1, hjust = 0,
  gp = grid::gpar(fontsize = 8, fontface = "bold")
)

column2 <- gridtext::richtext_grob(
  paste("not sigfnificant", "p < 0.05", sep = "<br>"),
  x = 0, halign = 0,
  vjust = 1, hjust = 0,
  gp = grid::gpar(fontsize = 8)
)

# Setup the gtable layout
legend <- gtable(
  # Widths of columns.
  widths = unit(c(12, 1), c("pt", "null")),
  heights = unit(1, "null")
)

# Add the grobs
legend <- gtable_add_grob(
  legend,
  grobs = list(column1, column2),
  t = c(1, 1),
  l = c(1, 2),
  clip = "off"
)

iris |>
  ggplot(aes(Species, Sepal.Length)) +
  geom_boxplot() +
  ggpubr::stat_pvalue_manual(stat.df, label = "significance") +
  theme_classic() +
  guides(
    custom = guide_custom(
      legend,
      title = "Significance"
    )
  )

like image 78
stefan Avatar answered Sep 19 '25 17:09

stefan