1

I am trying to extract the label text from a ggplot legend object, e.g. for this plot:

library(ggplot2)
(p <- ggplot(mtcars, aes(x=mpg, y=disp, color=as.character(cyl))) + geom_point())

enter image description here

I can extract the legends via

library(ggpubr)
legend <- ggpubr::get_legend(p)

Next, I would like to get the actual string values that are contained in the legend object, i.e. for this case "4", "6", "8". How can these values be retrieved from the legend object?

Note: I do not have the original data available, only the legend object.

1 Answer 1

3

First set up the legend:

library(ggplot2)
library(ggpubr)

p <- ggplot(mtcars, aes(x=mpg, y=disp, color=as.character(cyl))) + geom_point()

legendp <- ggpubr::get_legend(p)

From legendp$grobs[[1]], we know that the labels are probably stored in grobs 9 to 11:

legendp$grobs[[1]]
# TableGrob (7 x 6) "layout": 11 grobs
#     z     cells       name                                grob
# 1   1 (1-7,1-6) background rect[legend.background..rect.19172]
# 2   2 (2-2,2-5)      title             gTree[GRID.gTree.19173]
# 3   3 (4-4,2-2) key-3-1-bg        rect[legend.key..rect.19163]
# 4   4 (4-4,2-2)  key-3-1-1           points[GRID.points.19164]
# 5   5 (5-5,2-2) key-4-1-bg        rect[legend.key..rect.19166]
# 6   6 (5-5,2-2)  key-4-1-1           points[GRID.points.19167]
# 7   7 (6-6,2-2) key-5-1-bg        rect[legend.key..rect.19169]
# 8   8 (6-6,2-2)  key-5-1-1           points[GRID.points.19170]
# 9   9 (4-4,4-4)  label-3-3             gTree[GRID.gTree.19174]
# 10 10 (5-5,4-4)  label-4-3             gTree[GRID.gTree.19175]
# 11 11 (6-6,4-4)  label-5-3             gTree[GRID.gTree.19176]

Then we can unlist grobs 9 to 11 (with which(grepl("label", legendp$grobs[[1]]$layout$name)) to dynamically output the target grobs). The labels are stored under a sublist element with a name that starts with "children.guide.label" and ends with "label", therefore we can grep that pattern to get our target labels

legendp_grobs9_11 <- unlist(legendp$grobs[[1]]$grobs[which(grepl("label", legendp$grobs[[1]]$layout$name))])

unname(legendp_grobs9_11[grepl("children.guide.label.*text.*label$", names(legendp_grobs9_11))])
# [1] "4" "6" "8"

Another example to show it works.

library(tidyverse)
library(ggpubr)

p2 <- ggplot(diamonds, aes(cut, price, col = cut)) + geom_point()
p2

legendp2 <- get_legend(p2)
legendp2_grobs13_17 <- unlist(legendp2$grobs[[1]]$grobs[which(grepl("label", legendp2$grobs[[1]]$layout$name))])
unname(legendp2_grobs13_17[grepl("children.guide.label.*text.*label$", names(legendp2_grobs13_17))])
#> [1] "Fair"      "Good"      "Very Good" "Premium"   "Ideal"

Created on 2023-06-09 with reprex v2.0.2

Not the answer you're looking for? Browse other questions tagged or ask your own question.