From 3b8e1a14d697842cc354dd5014134406807cb9f4 Mon Sep 17 00:00:00 2001 From: Paul Schmidt Date: Wed, 5 Aug 2026 11:45:44 +0200 Subject: [PATCH] ggdesplot: leave cells with a missing value empty The gg path filled a missing value with grey50, which is hard to tell from the lightgray midpoint of the default RedGrayBlue scale, so a hole in the field read as a mid-range value. The lattice path leaves such a cell empty; set na.value on both fill scales to match it. --- NEWS.md | 2 ++ R/ggdesplot.R | 8 ++++++-- tests/testthat/test_ggdesplot_fixes.R | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index e3c6b96..c24bf83 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # desplot 1.11 () +* `ggdesplot()` now leaves cells with a missing value empty, as `desplot()` does. Previously they were filled with the ggplot2 default grey, which lies inside the range of the default red-gray-blue scale and so looked like a mid-range value. (P.Schmidt) + * `ggdesplot()` no longer draws a spurious `no_color` legend when `text` or `num` is used without `col`. (P.Schmidt) * `ggdesplot()` now facets on every conditioning variable in a formula such as `yield ~ col*row | site + rep`. Previously only the first was used and the others were silently dropped, overplotting cells. (P.Schmidt) diff --git a/R/ggdesplot.R b/R/ggdesplot.R index 57ad951..25bf8d1 100644 --- a/R/ggdesplot.R +++ b/R/ggdesplot.R @@ -482,17 +482,21 @@ ggdesplot <- function(data, out <- out + facet_wrap(panel.string, scales="free") + # Note, cells with a missing value are left empty instead of being filled + # with the ggplot2 default grey50, which is hard to tell from the lightgray + # midpoint of RedGrayBlue. The lattice version leaves such cells empty too. if(fill.type=="num") out <- out + #geom_tile(aes_string(fill = fill.string)) + geom_tile(aes(fill = .data[[fill.string]])) + - scale_fill_gradientn(colours=col.regions, guide="colorbar") + scale_fill_gradientn(colours=col.regions, guide="colorbar", + na.value="transparent") if(fill.type=="factor") out <- out + #geom_tile(aes_string(fill = fill.string)) + geom_tile(aes(fill = .data[[fill.string]])) + - scale_fill_manual(values=col.regions) + scale_fill_manual(values=col.regions, na.value="transparent") if(has.out1) out <- out + diff --git a/tests/testthat/test_ggdesplot_fixes.R b/tests/testthat/test_ggdesplot_fixes.R index 5584aa1..7a9df80 100644 --- a/tests/testthat/test_ggdesplot_fixes.R +++ b/tests/testthat/test_ggdesplot_fixes.R @@ -44,3 +44,23 @@ test_that("ggdesplot single conditioning variable keeps its panel labels", { p <- suppressWarnings(ggdesplot(besag.met, yield ~ col * row | county)) expect_equal(levels(p$data$.panel), paste0("C", 1:6)) }) + +test_that("ggdesplot leaves a cell with a missing value empty", { + # 4x4 field with a hole at col 2 / row 2, once numeric and once a factor + hole <- data.frame( + col = rep(1:4, times = 4), + row = rep(1:4, each = 4), + yield = c(1:5, NA, 7:16), + B = factor(c(rep("b1", 5), NA, rep("b2", 10))) + ) + + fill_num <- ggplot2::layer_data(ggdesplot(hole, yield ~ col * row), 1)$fill + expect_equal(sum(fill_num == "transparent"), 1L) + # the guard: the other 15 cells still get a real colour from col.regions, + # so the empty cell comes from the missing value and not from a broken scale + expect_equal(length(unique(fill_num[fill_num != "transparent"])), 15L) + + fill_fac <- ggplot2::layer_data(ggdesplot(hole, B ~ col * row), 1)$fill + expect_equal(sum(fill_fac == "transparent"), 1L) + expect_equal(length(unique(fill_fac[fill_fac != "transparent"])), 2L) +})