Skip to content

Commit c9adeed

Browse files
authored
allow fewer elements in named values vector in manual scales (#4471)
1 parent aafb06d commit c9adeed

File tree

4 files changed

+46
-25
lines changed

4 files changed

+46
-25
lines changed

NEWS.md

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

3+
* Manual scales now allow named vectors passed to `values` to contain fewer
4+
elements than existing in the data. Elements not present in values will be set
5+
to `NA` (@thomasp85, #3451)
6+
37
* Remove cross-inheritance of default discrete colour/fill scales and check the
48
type and aesthetic of function output if `type` is a function
59
(@thomasp85, #4149)

R/scale-manual.r

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#' - A character vector of breaks
2929
#' - A function that takes the limits as input and returns breaks
3030
#' as output
31+
#' @param na.value The aesthetic value to use for missing (`NA`) values
32+
#'
3133
#' @section Color Blindness:
3234
#' Many color palettes derived from RGB combinations (like the "rainbow" color
3335
#' palette) are not suitable to support all viewers, especially those with
@@ -80,38 +82,38 @@ NULL
8082

8183
#' @rdname scale_manual
8284
#' @export
83-
scale_colour_manual <- function(..., values, aesthetics = "colour", breaks = waiver()) {
84-
manual_scale(aesthetics, values, breaks, ...)
85+
scale_colour_manual <- function(..., values, aesthetics = "colour", breaks = waiver(), na.value = "grey50") {
86+
manual_scale(aesthetics, values, breaks, ..., na.value = na.value)
8587
}
8688

8789
#' @rdname scale_manual
8890
#' @export
89-
scale_fill_manual <- function(..., values, aesthetics = "fill", breaks = waiver()) {
90-
manual_scale(aesthetics, values, breaks, ...)
91+
scale_fill_manual <- function(..., values, aesthetics = "fill", breaks = waiver(), na.value = "grey50") {
92+
manual_scale(aesthetics, values, breaks, ..., na.value = na.value)
9193
}
9294

9395
#' @rdname scale_manual
9496
#' @export
95-
scale_size_manual <- function(..., values, breaks = waiver()) {
96-
manual_scale("size", values, breaks, ...)
97+
scale_size_manual <- function(..., values, breaks = waiver(), na.value = NA) {
98+
manual_scale("size", values, breaks, ..., na.value = na.value)
9799
}
98100

99101
#' @rdname scale_manual
100102
#' @export
101-
scale_shape_manual <- function(..., values, breaks = waiver()) {
102-
manual_scale("shape", values, breaks, ...)
103+
scale_shape_manual <- function(..., values, breaks = waiver(), na.value = NA) {
104+
manual_scale("shape", values, breaks, ..., na.value = na.value)
103105
}
104106

105107
#' @rdname scale_manual
106108
#' @export
107-
scale_linetype_manual <- function(..., values, breaks = waiver()) {
108-
manual_scale("linetype", values, breaks, ...)
109+
scale_linetype_manual <- function(..., values, breaks = waiver(), na.value = "blank") {
110+
manual_scale("linetype", values, breaks, ..., na.value = na.value)
109111
}
110112

111113
#' @rdname scale_manual
112114
#' @export
113-
scale_alpha_manual <- function(..., values, breaks = waiver()) {
114-
manual_scale("alpha", values, breaks, ...)
115+
scale_alpha_manual <- function(..., values, breaks = waiver(), na.value = NA) {
116+
manual_scale("alpha", values, breaks, ..., na.value = na.value)
115117
}
116118

117119
#' @rdname scale_manual
@@ -121,7 +123,7 @@ scale_discrete_manual <- function(aesthetics, ..., values, breaks = waiver()) {
121123
}
122124

123125

124-
manual_scale <- function(aesthetic, values = NULL, breaks = waiver(), ...) {
126+
manual_scale <- function(aesthetic, values = NULL, breaks = waiver(), limits = NULL, ...) {
125127
# check for missing `values` parameter, in lieu of providing
126128
# a default to all the different scale_*_manual() functions
127129
if (is_missing(values)) {
@@ -130,6 +132,10 @@ manual_scale <- function(aesthetic, values = NULL, breaks = waiver(), ...) {
130132
force(values)
131133
}
132134

135+
if (is.null(limits)) {
136+
limits <- names(values)
137+
}
138+
133139
# order values according to breaks
134140
if (is.vector(values) && is.null(names(values)) && !is.waive(breaks) &&
135141
!is.null(breaks) && !is.function(breaks)) {
@@ -146,5 +152,5 @@ manual_scale <- function(aesthetic, values = NULL, breaks = waiver(), ...) {
146152
}
147153
values
148154
}
149-
discrete_scale(aesthetic, "manual", pal, breaks = breaks, ...)
155+
discrete_scale(aesthetic, "manual", pal, breaks = breaks, limits = limits, ...)
150156
}

man/scale_manual.Rd

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

tests/testthat/test-scale-manual.r

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,12 @@ test_that("unnamed values match breaks in manual scales", {
8888

8989
test_that("limits works (#3262)", {
9090
# named charachter vector
91-
s1 <- scale_colour_manual(values = c("8" = "c", "4" = "a", "6" = "b"), limits = c("4", "8"))
91+
s1 <- scale_colour_manual(values = c("8" = "c", "4" = "a", "6" = "b"), limits = c("4", "8"), na.value = NA)
9292
s1$train(c("4", "6", "8"))
9393
expect_equal(s1$map(c("4", "6", "8")), c("a", NA, "c"))
9494

9595
# named charachter vector
96-
s2 <- scale_colour_manual(values = c("c", "a", "b"), limits = c("4", "8"))
96+
s2 <- scale_colour_manual(values = c("c", "a", "b"), limits = c("4", "8"), na.value = NA)
9797
s2$train(c("4", "6", "8"))
9898
expect_equal(s2$map(c("4", "6", "8")), c("c", NA, "a"))
9999
})

0 commit comments

Comments
 (0)