diff --git a/NEWS.md b/NEWS.md index 1fba13fba8..13cfd1dde9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,8 @@ * Patterns and gradients are now also enabled in `geom_sf()` (@teunbrand, #5716). * `stat_bin()` deals with non-finite breaks better (@teunbrand, #5665). +* When legends detect the presence of values in a layer, `NA` is now detected + if the data contains values outside the given breaks (@teunbrand, #5749). * `annotate()` now warns about `stat` or `position` arguments (@teunbrand, #5151) # ggplot2 3.5.0 diff --git a/R/guide-legend.R b/R/guide-legend.R index afcde6744f..c685cdd8c7 100644 --- a/R/guide-legend.R +++ b/R/guide-legend.R @@ -649,6 +649,19 @@ keep_key_data <- function(key, data, aes, show) { for (column in match) { keep <- keep | key$.value %in% data[[column]] } + + # NA might be included in breaks but originate from non-missing values that + # map to NA instead of *being* NA. We double-check if there are values + # outside the non-missing conventional limits. + is_na <- which(is.na(key$.value) & !keep) + if (length(is_na) > 0) { + na_keep <- FALSE + for (column in match) { + na_keep <- na_keep || !all(data[[column]] %in% key$.value) + } + keep[is_na] <- na_keep + } + keep } diff --git a/tests/testthat/test-draw-key.R b/tests/testthat/test-draw-key.R index 6e6b84f093..223bfd6d5c 100644 --- a/tests/testthat/test-draw-key.R +++ b/tests/testthat/test-draw-key.R @@ -96,6 +96,11 @@ test_that("keep_draw_key", { c(FALSE, TRUE) ) + # Missing values + key <- data_frame0(.value = c("A", "B", NA)) + data <- data_frame0(foo = c("A", "B", "C")) # 'C' should count as NA + expect_equal(keep_key_data(key, data, "foo", show = NA), c(TRUE, TRUE, TRUE)) + p <- ggplot(data.frame(x = 1:2), aes(x, x)) + geom_point( aes(colour = "point", alpha = "point"),