From 74e6960ff5db4c69a05672832ff968692d44aa55 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 7 Jan 2025 09:46:36 +0100 Subject: [PATCH 1/6] Avoid assigning NULL to list, thereby deleting the element --- R/coord-radial.R | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/R/coord-radial.R b/R/coord-radial.R index 1b4da20a23..59aaf59706 100644 --- a/R/coord-radial.R +++ b/R/coord-radial.R @@ -250,11 +250,18 @@ CoordRadial <- ggproto("CoordRadial", Coord, names(gdefs) <- aesthetics # Train theta guide - for (t in intersect(c("theta", "theta.sec"), aesthetics[!empty])) { - gdefs[[t]] <- guides[[t]]$train(gdefs[[t]], panel_params[[t]]) - gdefs[[t]] <- guides[[t]]$transform(gdefs[[t]], self, panel_params) - gdefs[[t]] <- guides[[t]]$get_layer_key(gdefs[[t]], layers) - } + t <- intersect(c("theta", "theta.sec"), aesthetics[!empty]) + gdefs[t] <- Map( + function(guide, guide_param, scale) { + guide_param$theme_suffix <- "theta" + guide_param <- guide$train(guide_param, scale) + guide_param <- guide$transform(guide_param, self, panel_params) + guide_param <- guide$get_layer_key(guide_param, layers) + }, + guide = guides[t], + guide_param = gdefs[t], + scale = panel_params[t] + ) if (!isFALSE(self$r_axis_inside)) { # For radial axis, we need to pretend that rotation starts at 0 and @@ -269,17 +276,18 @@ CoordRadial <- ggproto("CoordRadial", Coord, temp <- modify_list(panel_params, mod) # Train radial guide - for (r in intersect(c("r", "r.sec"), aesthetics[!empty])) { - gdefs[[r]] <- guides[[r]]$train(gdefs[[r]], panel_params[[r]]) - gdefs[[r]] <- guides[[r]]$transform(gdefs[[r]], self, temp) # Use temp - gdefs[[r]] <- guides[[r]]$get_layer_key(gdefs[[r]], layers) - } - - # Set theme suffixes - gdefs$theta$theme_suffix <- "theta" - gdefs$theta.sec$theme_suffix <- "theta" - gdefs$r$theme_suffix <- "r" - gdefs$r.sec$theme_suffix <- "r" + r <- intersect(c("r", "r.sec"), aesthetics[!empty]) + gdefs[r] <- Map( + function(guide, guide_param, scale) { + guide_param$theme_suffix <- "r" + guide_param <- guide$train(guide_param, scale) + guide_param <- guide$transform(guide_param, self, temp) + guide_param <- guide$get_layer_key(guide_param, layers) + }, + guide = guides[r], + guide_param = gdefs[r], + scale = panel_params[r] + ) panel_params$guides$update_params(gdefs) panel_params From 85762f8497eb155baf819aa0f110b52701b4e17b Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 7 Jan 2025 09:56:23 +0100 Subject: [PATCH 2/6] protect theta guide better against empty keys --- R/guide-axis-theta.R | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/R/guide-axis-theta.R b/R/guide-axis-theta.R index 7f4c3c9246..af96a337b6 100644 --- a/R/guide-axis-theta.R +++ b/R/guide-axis-theta.R @@ -63,22 +63,26 @@ GuideAxisTheta <- ggproto( transform = function(params, coord, panel_params) { - opposite_var <- setdiff(c("x", "y"), params$aesthetic) - opposite_value <- switch(params$position, top = , right = , theta.sec = -Inf, Inf) - if (is.unsorted(panel_params$inner_radius %||% NA)) { - opposite_value <- -opposite_value - } - if (nrow(params$key) > 0) { - params$key[[opposite_var]] <- opposite_value - } - if (nrow(params$decor) > 0) { - params$decor[[opposite_var]] <- opposite_value + position <- params$position + + if (!is.null(position)) { + opposite_var <- setdiff(c("x", "y"), params$aesthetic) + opposite_value <- switch(position, top = , right = , theta.sec = -Inf, Inf) + if (is.unsorted(panel_params$inner_radius %||% NA)) { + opposite_value <- -opposite_value + } + if (nrow(params$key) > 0) { + params$key[[opposite_var]] <- opposite_value + } + if (nrow(params$decor) > 0) { + params$decor[[opposite_var]] <- opposite_value + } } params <- GuideAxis$transform(params, coord, panel_params) key <- params$key - n <- nrow(key) + n <- vec_size(key) if (n < 1) { return(params) } From fc3aaf3f555e62296acee8519567d449058a85dc Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 7 Jan 2025 10:31:42 +0100 Subject: [PATCH 3/6] add test --- tests/testthat/test-coord-polar.R | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/testthat/test-coord-polar.R b/tests/testthat/test-coord-polar.R index 2b07d96b21..82ba6f73d6 100644 --- a/tests/testthat/test-coord-polar.R +++ b/tests/testthat/test-coord-polar.R @@ -197,6 +197,18 @@ test_that("radial coords can be reversed", { expect_equal(as.numeric(fwd$y), rev(as.numeric(rev$y))) }) +test_that("coord_radial can deal with empty breaks (#6271)", { + p <- ggplot_build( + ggplot(mtcars, aes(mpg, disp)) + + geom_point() + + coord_radial() + + scale_x_continuous(breaks = numeric()) + + scale_y_continuous(breaks = numeric()) + ) + guides <- p$layout$panel_params[[1]]$guides$guides + is_none <- vapply(guides, inherits, logical(1), what = "GuideNone") + expect_true(all(is_none)) +}) # Visual tests ------------------------------------------------------------ From 231a7ca6f57ecf2caf78a86be21dcc0d87b1f358 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 7 Jan 2025 10:33:21 +0100 Subject: [PATCH 4/6] add news bullet --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index dd574ac1aa..b50611803f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # ggplot2 (development version) +* `coord_radial()` now displays no axis instead of throwing an error when + a scale has no breaks (@teunbrand, #6271). * `guide_*()` can now accept two inside legend theme elements: `legend.position.inside` and `legend.justification.inside`, allowing inside legends to be placed at different positions. Only inside legends with the same From f6a1607914d218dde207182e7c6c957422027c9c Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 8 Jan 2025 09:20:28 +0100 Subject: [PATCH 5/6] Fix partial match --- R/guides-.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/guides-.R b/R/guides-.R index debb99237e..83b34dd833 100644 --- a/R/guides-.R +++ b/R/guides-.R @@ -541,7 +541,7 @@ Guides <- ggproto( # prepare output for (i in vec_seq_along(groups)) { adjust <- NULL - position <- groups$key$position[i] + position <- groups$key$positions[i] if (position == "inside") { adjust <- theme( legend.position.inside = groups$key$coord[[i]], From de2648b4757b41a573c57641b0526f0b1c54ca6e Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 13 Jan 2025 09:18:04 +0100 Subject: [PATCH 6/6] fix another partial match --- R/guides-.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/guides-.R b/R/guides-.R index 83b34dd833..c1d697a1a6 100644 --- a/R/guides-.R +++ b/R/guides-.R @@ -526,7 +526,7 @@ Guides <- ggproto( coord <- coord %||% default_inside_position %||% just groups$justs[[i]] <- just - groups$coord[[i]] <- coord + groups$coords[[i]] <- coord } groups <- vec_group_loc(vec_slice(groups, keep)) @@ -544,7 +544,7 @@ Guides <- ggproto( position <- groups$key$positions[i] if (position == "inside") { adjust <- theme( - legend.position.inside = groups$key$coord[[i]], + legend.position.inside = groups$key$coords[[i]], legend.justification.inside = groups$key$justs[[i]] ) }