Skip to content

Commit ea6e1c5

Browse files
authored
NA in manual scale with named values (#5288)
* Preserve NA in manual scales * Add test * Add news bullet * Also fix #5298
1 parent 222d33d commit ea6e1c5

File tree

4 files changed

+36
-2
lines changed

4 files changed

+36
-2
lines changed

NEWS.md

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

3+
* Legends in `scale_*_manual()` can show `NA` values again when the `values` is
4+
a named vector (@teunbrand, #5214, #5286).
5+
6+
* `scale_*_manual()` with a named `values` argument now emits a warning when
7+
none of those names match the values found in the data (@teunbrand, #5298).
8+
39
* `coord_munch()` can now close polygon shapes (@teunbrand, #3271)
410

511
* You can now omit either `xend` or `yend` from `geom_segment()` as only one

R/scale-manual.R

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ scale_discrete_manual <- function(aesthetics, ..., values, breaks = waiver()) {
141141
manual_scale(aesthetics, values, breaks, ...)
142142
}
143143

144-
manual_scale <- function(aesthetic, values = NULL, breaks = waiver(), ..., limits = NULL) {
144+
manual_scale <- function(aesthetic, values = NULL, breaks = waiver(), ...,
145+
limits = NULL) {
145146
# check for missing `values` parameter, in lieu of providing
146147
# a default to all the different scale_*_manual() functions
147148
if (is_missing(values)) {
@@ -152,7 +153,17 @@ manual_scale <- function(aesthetic, values = NULL, breaks = waiver(), ..., limit
152153

153154
if (is.null(limits) && !is.null(names(values))) {
154155
# Limits as function to access `values` names later on (#4619)
155-
limits <- function(x) intersect(x, names(values)) %||% character()
156+
force(aesthetic)
157+
limits <- function(x) {
158+
x <- intersect(x, c(names(values), NA)) %||% character()
159+
if (length(x) < 1) {
160+
cli::cli_warn(paste0(
161+
"No shared levels found between {.code names(values)} of the manual ",
162+
"scale and the data's {.field {aesthetic}} values."
163+
))
164+
}
165+
x
166+
}
156167
}
157168

158169
# order values according to breaks

tests/testthat/_snaps/scale-manual.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# names of values used in manual scales
2+
3+
No shared levels found between `names(values)` of the manual scale and the data's colour values.
4+

tests/testthat/test-scale-manual.R

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ test_that("names of values used in manual scales", {
66
s2 <- scale_colour_manual(values = c("8" = "c", "4" = "a", "6" = "b"), na.value = NA)
77
s2$train(c("4", "8"))
88
expect_equal(s2$map(c("4", "6", "8")), c("a", NA, "c"))
9+
expect_equal(s2$get_limits(), c("4", "8"))
10+
11+
s3 <- scale_colour_manual(values = c("8" = "c", "4" = "a", "6" = "b"), na.value = "x")
12+
s3$train(c("4", "8", NA))
13+
expect_equal(s3$map(c("4", "6", "8")), c("a", "x", "c"))
14+
expect_equal(s3$get_limits(), c("4", "8", NA))
15+
16+
# Names do not match data
17+
s <- scale_colour_manual(values = c("foo" = "x", "bar" = "y"))
18+
s$train(c("A", "B"))
19+
expect_snapshot_warning(
20+
expect_equal(s$get_limits(), character())
21+
)
922
})
1023

1124

0 commit comments

Comments
 (0)