Skip to content

Commit d262ffb

Browse files
authored
Expression aesthetics (#6685)
* add normalisation step for label ingestion * reuse normalisation in scale labels * add validation step in GeomText and GeomLabel * add snapshot test * add news bullet * add comments * typos * fix bug
1 parent d7cca80 commit d262ffb

File tree

7 files changed

+102
-21
lines changed

7 files changed

+102
-21
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
### Bug fixes
44

5+
* `geom_text()` and `geom_label()` accept expressions as the `label` aesthetic
6+
(@teunbrand, #6638)
57
* Fixed regression where `draw_key_rect()` stopped using `fill` colours
68
(@mitchelloharawild, #6609).
79
* Fixed regression where `scale_{x,y}_*()` threw an error when an expression

R/geom-label.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ GeomLabel <- ggproto("GeomLabel", Geom,
8383
if (parse) {
8484
lab <- parse_safe(as.character(lab))
8585
}
86+
lab <- validate_labels(lab)
8687

8788
data <- coord$transform(data, panel_params)
8889
data$vjust <- compute_just(data$vjust, data$y, data$x, data$angle)

R/geom-text.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ GeomText <- ggproto(
2323
if (parse) {
2424
lab <- parse_safe(as.character(lab))
2525
}
26+
lab <- validate_labels(lab)
2627

2728
data <- coord$transform(data, panel_params)
2829

R/layer.R

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ layer <- function(geom = NULL, stat = NULL,
176176
if (check.aes && length(extra_aes) > 0) {
177177
cli::cli_warn("Ignoring unknown aesthetics: {.field {extra_aes}}", call = call_env)
178178
}
179+
aes_params$label <- normalise_label(aes_params$label)
179180

180181
# adjust the legend draw key if requested
181182
geom <- set_draw_key(geom, key_glyph %||% params$key_glyph)
@@ -552,6 +553,7 @@ Layer <- ggproto("Layer", NULL,
552553

553554
# Evaluate aesthetics
554555
evaled <- eval_aesthetics(aesthetics, data)
556+
evaled$label <- normalise_label(evaled$label)
555557
plot@scales$add_defaults(evaled, plot@plot_env)
556558

557559
# Check for discouraged usage in mapping
@@ -963,3 +965,20 @@ cleanup_mismatched_data <- function(data, n, fun) {
963965
data[failed] <- NULL
964966
data
965967
}
968+
969+
normalise_label <- function(label) {
970+
if (is.null(label)) {
971+
return(NULL)
972+
}
973+
if (obj_is_list(label)) {
974+
# Ensure that each element in the list has length 1
975+
label[lengths(label) == 0] <- ""
976+
labels <- lapply(labels, `[`, 1)
977+
}
978+
if (is.expression(label)) {
979+
# Classed expressions, when converted to lists, retain their class.
980+
# The unclass is needed to properly treat it as a vctrs-compatible list.
981+
label <- unclass(as.list(label))
982+
}
983+
label
984+
}

R/scale-.R

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,18 +1182,7 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale,
11821182
call = self$call
11831183
)
11841184
}
1185-
1186-
if (obj_is_list(labels)) {
1187-
# Guard against list with empty elements
1188-
labels[lengths(labels) == 0] <- ""
1189-
# Make sure each element is scalar
1190-
labels <- lapply(labels, `[`, 1)
1191-
}
1192-
if (is.expression(labels)) {
1193-
labels <- as.list(labels)
1194-
}
1195-
1196-
labels
1185+
normalise_label(labels)
11971186
},
11981187

11991188
clone = function(self) {
@@ -1436,11 +1425,7 @@ ScaleDiscrete <- ggproto("ScaleDiscrete", Scale,
14361425
# Need to ensure that if breaks were dropped, corresponding labels are too
14371426
labels <- labels[attr(breaks, "pos")]
14381427
}
1439-
1440-
if (is.expression(labels)) {
1441-
labels <- as.list(labels)
1442-
}
1443-
labels
1428+
normalise_label(labels)
14441429
},
14451430

14461431
clone = function(self) {
@@ -1688,10 +1673,7 @@ ScaleBinned <- ggproto("ScaleBinned", Scale,
16881673
call = self$call
16891674
)
16901675
}
1691-
if (is.expression(labels)) {
1692-
labels <- as.list(labels)
1693-
}
1694-
labels
1676+
normalise_label(labels)
16951677
},
16961678

16971679
clone = function(self) {
Lines changed: 64 additions & 0 deletions
Loading

tests/testthat/test-geom-text.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ test_that("geom_text() rejects exotic units", {
3333
)
3434
})
3535

36+
test_that("geom_text() can display expressions", {
37+
38+
df <- data_frame0(x = 1:2, y = 1:2)
39+
df$exp <- expression(alpha + beta^2, gamma * sqrt(delta))
40+
41+
expect_doppelganger(
42+
"geom_text with expressions",
43+
ggplot(df, aes(x, y, label = exp)) +
44+
geom_text()
45+
)
46+
})
47+
3648
# compute_just ------------------------------------------------------------
3749

3850
test_that("vertical and horizontal positions are equivalent", {

0 commit comments

Comments
 (0)