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())
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.
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