Skip to content

Commit

Permalink
Label accessor (#6078)
Browse files Browse the repository at this point in the history
* guides merge aesthetics

* add getter for completed plot labels

* incorporate getter in tests

* document
  • Loading branch information
teunbrand authored Sep 23, 2024
1 parent 7f6d5bf commit 171664b
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 46 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ export(get_alt_text)
export(get_element_tree)
export(get_geom_defaults)
export(get_guide_data)
export(get_labs)
export(get_last_plot)
export(get_layer_data)
export(get_layer_grob)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ggplot2 (development version)

* New `get_labs()` function for retrieving completed plot labels
(@teunbrand, #6008).
* Built-in `theme_*()` functions now have `ink` and `paper` arguments to control
foreground and background colours respectively (@teunbrand)
* The `summary()` method for ggplots is now more terse about facets
Expand Down
1 change: 1 addition & 0 deletions R/guide-colorbar.R
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ GuideColourbar <- ggproto(
merge = function(self, params, new_guide, new_params) {
new_params$key$.label <- new_params$key$.value <- NULL
params$key <- vec_cbind(params$key, new_params$key)
params$aesthetic <- union(params$aesthetic, new_params$aesthetic)
return(list(guide = self, params = params))
},

Expand Down
1 change: 1 addition & 0 deletions R/guide-legend.R
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ GuideLegend <- ggproto(
cli::cli_warn("Duplicated {.arg override.aes} is ignored.")
}
params$override.aes <- params$override.aes[!duplicated(nms)]
params$aesthetic <- union(params$aesthetic, new_params$aesthetic)

list(guide = self, params = params)
},
Expand Down
33 changes: 33 additions & 0 deletions R/labels.R
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,39 @@ ggtitle <- function(label, subtitle = waiver()) {
labs(title = label, subtitle = subtitle)
}

#' @rdname labs
#' @export
#' @param plot A ggplot object
#' @description
#' `get_labs()` retrieves completed labels from a plot.
get_labs <- function(plot = get_last_plot()) {
plot <- ggplot_build(plot)

labs <- plot$plot$labels

xy_labs <- rename(
c(x = plot$layout$resolve_label(plot$layout$panel_scales_x[[1]], labs),
y = plot$layout$resolve_label(plot$layout$panel_scales_y[[1]], labs)),
c(x.primary = "x", x.secondary = "x.sec",
y.primary = "y", y.secondary = "y.sec")
)

labs <- defaults(xy_labs, labs)

guides <- plot$plot$guides
if (length(guides$aesthetics) == 0) {
return(labs)
}

for (aes in guides$aesthetics) {
param <- guides$get_params(aes)
aes <- param$aesthetic # Can have length > 1 when guide was merged
title <- vec_set_names(rep(list(param$title), length(aes)), aes)
labs <- defaults(title, labs)
}
labs
}

#' Extract alt text from a plot
#'
#' This function returns a text that can be used as alt-text in webpages etc.
Expand Down
7 changes: 7 additions & 0 deletions man/labs.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 25 additions & 46 deletions tests/testthat/test-labels.R
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,22 @@ test_that("setting guide labels works", {
test_that("Labels from default stat mapping are overwritten by default labels", {
p <- ggplot(mpg, aes(displ, hwy)) +
geom_density2d()
labels <- ggplot_build(p)$plot$labels

labels <- get_labs(p)
expect_equal(labels$colour[1], "colour")
expect_true(attr(labels$colour, "fallback"))

p <- p + geom_smooth(aes(color = drv), method = "lm", formula = y ~ x)
labels <- ggplot_build(p)$plot$labels

expect_equal(labels$colour, "drv")
expect_equal(get_labs(p)$colour, "drv")
})

test_that("Labels can be extracted from attributes", {
df <- mtcars
attr(df$mpg, "label") <- "Miles per gallon"

p <- ggplot(df, aes(mpg, disp)) + geom_point()
labels <- ggplot_build(p)$plot$labels

labels <- get_labs(p)
expect_equal(labels$x, "Miles per gallon")
expect_equal(labels$y, "disp")
})
Expand All @@ -79,14 +77,10 @@ test_that("Labels from static aesthetics are ignored (#6003)", {
df <- data.frame(x = 1, y = 1, f = 1)

p <- ggplot(df, aes(x, y, colour = f)) + geom_point()
labels <- ggplot_build(p)$plot$labels

expect_equal(labels$colour, "f")
expect_equal(get_labs(p)$colour, "f")

p <- ggplot(df, aes(x, y, colour = f)) + geom_point(colour = "blue")
labels <- ggplot_build(p)$plot$labels

expect_null(labels$colour)
expect_null(get_labs(p)$colour)
})

test_that("alt text is returned", {
Expand Down Expand Up @@ -140,24 +134,25 @@ test_that("position axis label hierarchy works as intended", {
geom_point(size = 5)

p <- ggplot_build(p)
resolve_label <- function(x) p$layout$resolve_label(x, p$plot$labels)

# In absence of explicit title, get title from mapping
expect_identical(
p$layout$resolve_label(p$layout$panel_scales_x[[1]], p$plot$labels),
resolve_label(p$layout$panel_scales_x[[1]]),
list(secondary = NULL, primary = "foo")
)
expect_identical(
p$layout$resolve_label(p$layout$panel_scales_y[[1]], p$plot$labels),
resolve_label(p$layout$panel_scales_y[[1]]),
list(primary = "bar", secondary = NULL)
)

# Scale name overrules mapping label
expect_identical(
p$layout$resolve_label(scale_x_continuous("Baz"), p$plot$labels),
resolve_label(scale_x_continuous("Baz")),
list(secondary = NULL, primary = "Baz")
)
expect_identical(
p$layout$resolve_label(scale_y_continuous("Qux"), p$plot$labels),
resolve_label(scale_y_continuous("Qux")),
list(primary = "Qux", secondary = NULL)
)

Expand All @@ -167,23 +162,23 @@ test_that("position axis label hierarchy works as intended", {
p$plot$layers
)
expect_identical(
p$layout$resolve_label(scale_x_continuous("Baz"), p$plot$labels),
resolve_label(scale_x_continuous("Baz")),
list(secondary = NULL, primary = "quuX")
)
expect_identical(
p$layout$resolve_label(scale_y_continuous("Qux"), p$plot$labels),
resolve_label(scale_y_continuous("Qux")),
list(primary = "corgE", secondary = NULL)
)

# Secondary axis names work
xsec <- scale_x_continuous("Baz", sec.axis = dup_axis(name = "grault"))
expect_identical(
p$layout$resolve_label(xsec, p$plot$labels),
resolve_label(xsec),
list(secondary = "grault", primary = "quuX")
)
ysec <- scale_y_continuous("Qux", sec.axis = dup_axis(name = "garply"))
expect_identical(
p$layout$resolve_label(ysec, p$plot$labels),
resolve_label(ysec),
list(primary = "corgE", secondary = "garply")
)

Expand All @@ -194,12 +189,12 @@ test_that("position axis label hierarchy works as intended", {
p$plot$layers
)
expect_identical(
p$layout$resolve_label(xsec, p$plot$labels),
resolve_label(xsec),
list(secondary = "waldo", primary = "quuX")
)
ysec <- scale_y_continuous("Qux", sec.axis = dup_axis(name = "garply"))
expect_identical(
p$layout$resolve_label(ysec, p$plot$labels),
resolve_label(ysec),
list(primary = "corgE", secondary = "fred")
)
})
Expand All @@ -220,31 +215,20 @@ test_that("moving guide positions lets titles follow", {
),
p$plot$layers
)
expect_identical(
p$layout$resolve_label(p$layout$panel_scales_x[[1]], p$plot$labels),
list(secondary = NULL, primary = "baz")
)
expect_identical(
p$layout$resolve_label(p$layout$panel_scales_y[[1]], p$plot$labels),
list(primary = "qux", secondary = NULL)
)
labs <- get_labs(p)
expect <- list(x = "baz", x.sec = NULL, y = "qux", y.sec = NULL)
expect_identical(labs[names(expect)], expect)

# Guides at secondary positions (changes order of primary/secondary)
# Guides at secondary positions
p$layout$setup_panel_guides(
guides_list(
list(x = guide_axis("baz", position = "top"),
y = guide_axis("qux", position = "right"))
),
p$plot$layers
)
expect_identical(
p$layout$resolve_label(p$layout$panel_scales_x[[1]], p$plot$labels),
list(primary = "baz", secondary = NULL)
)
expect_identical(
p$layout$resolve_label(p$layout$panel_scales_y[[1]], p$plot$labels),
list(secondary = NULL, primary = "qux")
)
labs <- get_labs(p)
expect_identical(labs[names(expect)], expect)

# Primary guides at secondary positions with
# secondary guides at primary positions
Expand All @@ -257,14 +241,9 @@ test_that("moving guide positions lets titles follow", {
),
p$plot$layers
)
expect_identical(
p$layout$resolve_label(p$layout$panel_scales_x[[1]], p$plot$labels),
list(primary = "baz", secondary = "quux")
)
expect_identical(
p$layout$resolve_label(p$layout$panel_scales_y[[1]], p$plot$labels),
list(secondary = "corge", primary = "qux")
)
labs <- get_labs(p)
expect[c("x.sec", "y.sec")] <- list("quux", "corge")
expect_identical(labs[names(expect)], expect)
})

# Visual tests ------------------------------------------------------------
Expand Down

0 comments on commit 171664b

Please sign in to comment.