diff --git a/NEWS.md b/NEWS.md index c7ed2a0668..99c4be476d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # ggplot2 (development version) +* The default width of `geom_bar()` is now based on panel-wise resolution of + the data, rather than global resolution (@teunbrand, #4336). * To apply dodging more consistently in violin plots, `stat_ydensity()` now has a `drop` argument to keep or discard groups with 1 observation. * Aesthetics listed in `geom_*()` and `stat_*()` layers now point to relevant diff --git a/R/geom-bar.R b/R/geom-bar.R index ab86d06050..a1007a3678 100644 --- a/R/geom-bar.R +++ b/R/geom-bar.R @@ -144,7 +144,10 @@ GeomBar <- ggproto("GeomBar", GeomRect, data$flipped_aes <- params$flipped_aes data <- flip_data(data, params$flipped_aes) data$width <- data$width %||% - params$width %||% (resolution(data$x, FALSE) * 0.9) + params$width %||% (min(vapply( + split(data$x, data$PANEL), + resolution, numeric(1), zero = FALSE + )) * 0.9) data$just <- params$just %||% 0.5 data <- transform(data, ymin = pmin(y, 0), ymax = pmax(y, 0), diff --git a/tests/testthat/test-geom-bar.R b/tests/testthat/test-geom-bar.R index b36a9c401e..1c15b96a9c 100644 --- a/tests/testthat/test-geom-bar.R +++ b/tests/testthat/test-geom-bar.R @@ -24,3 +24,27 @@ test_that("geom_bar works in both directions", { y$flipped_aes <- NULL expect_identical(x, flip_data(y, TRUE)) }) + +test_that("geom_bar default widths considers panels", { + + dat <- data_frame0(x = c(1:2, 1:2 + 0.1), y = 1, + PANEL = factor(rep(1:2, each = 2))) + + layer <- geom_bar() + params <- layer$geom_params + + # Default should be panel-wise resolution (0.9), not data-wise resolution (0.1) + new <- layer$geom$setup_data(dat, params) + expect_equal( + new$xmax - new$xmin, + rep(0.9, 4) + ) + + # Check that default can still be overridden + params$width <- 0.5 + new <- layer$geom$setup_data(dat, params) + expect_equal( + new$xmax - new$xmin, + rep(0.5, 4) + ) +})