Skip to content

Commit 3b3ce35

Browse files
committed
Label accessor (tidyverse#6078)
* guides merge aesthetics * add getter for completed plot labels * incorporate getter in tests * document
1 parent 905825d commit 3b3ce35

File tree

8 files changed

+71
-41
lines changed

8 files changed

+71
-41
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ Config/testthat/edition: 3
7979
Encoding: UTF-8
8080
LazyData: true
8181
Roxygen: list(markdown = TRUE)
82-
RoxygenNote: 7.3.1
82+
RoxygenNote: 7.3.2
8383
Collate:
8484
'ggproto.R'
8585
'ggplot-global.R'

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ export(geom_vline)
422422
export(get_alt_text)
423423
export(get_element_tree)
424424
export(get_guide_data)
425+
export(get_labs)
425426
export(gg_dep)
426427
export(ggplot)
427428
export(ggplotGrob)

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# ggplot2 (development version)
22

3+
* New `get_labs()` function for retrieving completed plot labels
4+
(@teunbrand, #6008).
35
* A new `ggplot_build()` S3 method for <ggplot_built> classes was added, which
46
returns input unaltered (@teunbrand, #5800).
57

R/guide-colorbar.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ GuideColourbar <- ggproto(
266266
merge = function(self, params, new_guide, new_params) {
267267
new_params$key$.label <- new_params$key$.value <- NULL
268268
params$key <- vec_cbind(params$key, new_params$key)
269+
params$aesthetic <- union(params$aesthetic, new_params$aesthetic)
269270
return(list(guide = self, params = params))
270271
},
271272

R/guide-legend.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ GuideLegend <- ggproto(
204204
cli::cli_warn("Duplicated {.arg override.aes} is ignored.")
205205
}
206206
params$override.aes <- params$override.aes[!duplicated(nms)]
207+
params$aesthetic <- union(params$aesthetic, new_params$aesthetic)
207208

208209
list(guide = self, params = params)
209210
},

R/labels.R

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,39 @@ ggtitle <- function(label, subtitle = waiver()) {
105105
labs(title = label, subtitle = subtitle)
106106
}
107107

108+
#' @rdname labs
109+
#' @export
110+
#' @param plot A ggplot object
111+
#' @description
112+
#' `get_labs()` retrieves completed labels from a plot.
113+
get_labs <- function(plot = get_last_plot()) {
114+
plot <- ggplot_build(plot)
115+
116+
labs <- plot$plot$labels
117+
118+
xy_labs <- rename(
119+
c(x = plot$layout$resolve_label(plot$layout$panel_scales_x[[1]], labs),
120+
y = plot$layout$resolve_label(plot$layout$panel_scales_y[[1]], labs)),
121+
c(x.primary = "x", x.secondary = "x.sec",
122+
y.primary = "y", y.secondary = "y.sec")
123+
)
124+
125+
labs <- defaults(xy_labs, labs)
126+
127+
guides <- plot$plot$guides
128+
if (length(guides$aesthetics) == 0) {
129+
return(labs)
130+
}
131+
132+
for (aes in guides$aesthetics) {
133+
param <- guides$get_params(aes)
134+
aes <- param$aesthetic # Can have length > 1 when guide was merged
135+
title <- vec_set_names(rep(list(param$title), length(aes)), aes)
136+
labs <- defaults(title, labs)
137+
}
138+
labs
139+
}
140+
108141
#' Extract alt text from a plot
109142
#'
110143
#' This function returns a text that can be used as alt-text in webpages etc.

man/labs.Rd

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-labels.R

Lines changed: 25 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ test_that("Labels from default stat mapping are overwritten by default labels",
5353
p <- ggplot(mpg, aes(displ, hwy)) +
5454
geom_density2d()
5555

56-
expect_equal(p$labels$colour[1], "colour")
57-
expect_true(attr(p$labels$colour, "fallback"))
56+
labels <- get_labs(p)
57+
expect_equal(labels$colour[1], "colour")
58+
expect_true(attr(labels$colour, "fallback"))
5859

59-
p <- p + geom_smooth(aes(color = drv))
60-
61-
expect_equal(p$labels$colour, "drv")
60+
p <- p + geom_smooth(aes(color = drv), method = "lm", formula = y ~ x)
61+
expect_equal(get_labs(p)$colour, "drv")
6262
})
6363

6464
test_that("alt text is returned", {
@@ -97,24 +97,25 @@ test_that("position axis label hierarchy works as intended", {
9797
geom_point(size = 5)
9898

9999
p <- ggplot_build(p)
100+
resolve_label <- function(x) p$layout$resolve_label(x, p$plot$labels)
100101

101102
# In absence of explicit title, get title from mapping
102103
expect_identical(
103-
p$layout$resolve_label(p$layout$panel_scales_x[[1]], p$plot$labels),
104+
resolve_label(p$layout$panel_scales_x[[1]]),
104105
list(secondary = NULL, primary = "foo")
105106
)
106107
expect_identical(
107-
p$layout$resolve_label(p$layout$panel_scales_y[[1]], p$plot$labels),
108+
resolve_label(p$layout$panel_scales_y[[1]]),
108109
list(primary = "bar", secondary = NULL)
109110
)
110111

111112
# Scale name overrules mapping label
112113
expect_identical(
113-
p$layout$resolve_label(scale_x_continuous("Baz"), p$plot$labels),
114+
resolve_label(scale_x_continuous("Baz")),
114115
list(secondary = NULL, primary = "Baz")
115116
)
116117
expect_identical(
117-
p$layout$resolve_label(scale_y_continuous("Qux"), p$plot$labels),
118+
resolve_label(scale_y_continuous("Qux")),
118119
list(primary = "Qux", secondary = NULL)
119120
)
120121

@@ -124,23 +125,23 @@ test_that("position axis label hierarchy works as intended", {
124125
p$plot$layers
125126
)
126127
expect_identical(
127-
p$layout$resolve_label(scale_x_continuous("Baz"), p$plot$labels),
128+
resolve_label(scale_x_continuous("Baz")),
128129
list(secondary = NULL, primary = "quuX")
129130
)
130131
expect_identical(
131-
p$layout$resolve_label(scale_y_continuous("Qux"), p$plot$labels),
132+
resolve_label(scale_y_continuous("Qux")),
132133
list(primary = "corgE", secondary = NULL)
133134
)
134135

135136
# Secondary axis names work
136137
xsec <- scale_x_continuous("Baz", sec.axis = dup_axis(name = "grault"))
137138
expect_identical(
138-
p$layout$resolve_label(xsec, p$plot$labels),
139+
resolve_label(xsec),
139140
list(secondary = "grault", primary = "quuX")
140141
)
141142
ysec <- scale_y_continuous("Qux", sec.axis = dup_axis(name = "garply"))
142143
expect_identical(
143-
p$layout$resolve_label(ysec, p$plot$labels),
144+
resolve_label(ysec),
144145
list(primary = "corgE", secondary = "garply")
145146
)
146147

@@ -151,12 +152,12 @@ test_that("position axis label hierarchy works as intended", {
151152
p$plot$layers
152153
)
153154
expect_identical(
154-
p$layout$resolve_label(xsec, p$plot$labels),
155+
resolve_label(xsec),
155156
list(secondary = "waldo", primary = "quuX")
156157
)
157158
ysec <- scale_y_continuous("Qux", sec.axis = dup_axis(name = "garply"))
158159
expect_identical(
159-
p$layout$resolve_label(ysec, p$plot$labels),
160+
resolve_label(ysec),
160161
list(primary = "corgE", secondary = "fred")
161162
)
162163
})
@@ -177,31 +178,20 @@ test_that("moving guide positions lets titles follow", {
177178
),
178179
p$plot$layers
179180
)
180-
expect_identical(
181-
p$layout$resolve_label(p$layout$panel_scales_x[[1]], p$plot$labels),
182-
list(secondary = NULL, primary = "baz")
183-
)
184-
expect_identical(
185-
p$layout$resolve_label(p$layout$panel_scales_y[[1]], p$plot$labels),
186-
list(primary = "qux", secondary = NULL)
187-
)
181+
labs <- get_labs(p)
182+
expect <- list(x = "baz", x.sec = NULL, y = "qux", y.sec = NULL)
183+
expect_identical(labs[names(expect)], expect)
188184

189-
# Guides at secondary positions (changes order of primary/secondary)
185+
# Guides at secondary positions
190186
p$layout$setup_panel_guides(
191187
guides_list(
192188
list(x = guide_axis("baz", position = "top"),
193189
y = guide_axis("qux", position = "right"))
194190
),
195191
p$plot$layers
196192
)
197-
expect_identical(
198-
p$layout$resolve_label(p$layout$panel_scales_x[[1]], p$plot$labels),
199-
list(primary = "baz", secondary = NULL)
200-
)
201-
expect_identical(
202-
p$layout$resolve_label(p$layout$panel_scales_y[[1]], p$plot$labels),
203-
list(secondary = NULL, primary = "qux")
204-
)
193+
labs <- get_labs(p)
194+
expect_identical(labs[names(expect)], expect)
205195

206196
# Primary guides at secondary positions with
207197
# secondary guides at primary positions
@@ -214,14 +204,9 @@ test_that("moving guide positions lets titles follow", {
214204
),
215205
p$plot$layers
216206
)
217-
expect_identical(
218-
p$layout$resolve_label(p$layout$panel_scales_x[[1]], p$plot$labels),
219-
list(primary = "baz", secondary = "quux")
220-
)
221-
expect_identical(
222-
p$layout$resolve_label(p$layout$panel_scales_y[[1]], p$plot$labels),
223-
list(secondary = "corge", primary = "qux")
224-
)
207+
labs <- get_labs(p)
208+
expect[c("x.sec", "y.sec")] <- list("quux", "corge")
209+
expect_identical(labs[names(expect)], expect)
225210
})
226211

227212
# Visual tests ------------------------------------------------------------

0 commit comments

Comments
 (0)