diff --git a/NEWS.md b/NEWS.md index 7fbbc1967b..7f870c7424 100644 --- a/NEWS.md +++ b/NEWS.md @@ -152,6 +152,8 @@ (@teunbrand, #5945). * (internal) The summary function of `stat_summary()` and `stat_summary_bin()` is setup once in total instead of once per group (@teunbrand, #5971) +* `facet_grid(space = "free")` can now be combined with `coord_fixed()` + (@teunbrand, #4584). # ggplot2 3.5.1 diff --git a/R/facet-.R b/R/facet-.R index 780c8bd184..a5e6f35101 100644 --- a/R/facet-.R +++ b/R/facet-.R @@ -139,18 +139,22 @@ Facet <- ggproto("Facet", NULL, free <- params$free %||% list(x = FALSE, y = FALSE) space <- params$space_free %||% list(x = FALSE, y = FALSE) - if ((free$x || free$y) && !coord$is_free()) { - cli::cli_abort( - "{.fn {snake_class(self)}} can't use free scales with \\ - {.fn {snake_class(coord)}}." - ) - } - aspect_ratio <- theme$aspect.ratio if (!is.null(aspect_ratio) && (space$x || space$y)) { cli::cli_abort("Free scales cannot be mixed with a fixed aspect ratio.") } + if (!coord$is_free()) { + if (space$x && space$y) { + aspect_ratio <- aspect_ratio %||% coord$ratio + } else if (free$x || free$y) { + cli::cli_abort( + "{.fn {snake_class(self)}} can't use free scales with \\ + {.fn {snake_class(coord)}}." + ) + } + } + table <- self$init_gtable( panels, layout, theme, ranges, params, aspect_ratio = aspect_ratio %||% coord$aspect(ranges[[1]]) @@ -219,7 +223,7 @@ Facet <- ggproto("Facet", NULL, if (space$y) { idx <- layout$PANEL[layout$COL == 1] heights <- vapply(idx, function(i) diff(ranges[[i]]$y.range), numeric(1)) - heights <- unit(heights, "null") + heights <- unit(heights * abs(aspect_ratio %||% 1), "null") } # Build gtable diff --git a/tests/testthat/test-facet-layout.R b/tests/testthat/test-facet-layout.R index 767abe5c8c..a008a0c80d 100644 --- a/tests/testthat/test-facet-layout.R +++ b/tests/testthat/test-facet-layout.R @@ -253,6 +253,23 @@ test_that("facet_grid throws errors at bad layout specs", { expect_snapshot_error(ggplotGrob(p)) }) +test_that("facet_grid can respect coord aspect with free scales/space", { + df <- expand.grid(x = letters[1:6], y = LETTERS[1:3]) + p <- ggplot(df, aes(x, y)) + + geom_tile() + + facet_grid( + rows = vars(y == "C"), + cols = vars(x %in% c("e", "f")), + scales = "free", space = "free" + ) + + coord_fixed(3, expand = FALSE) + gt <- ggplotGrob(p) + width <- gt$widths[panel_cols(gt)$l] + height <- gt$heights[panel_rows(gt)$t] + expect_equal(as.numeric(width), c(4, 2)) + expect_equal(as.numeric(height), c(6, 3)) +}) + test_that("facet_wrap and facet_grid throws errors when using reserved words", { mtcars2 <- mtcars mtcars2$PANEL <- mtcars2$cyl