diff --git a/NEWS.md b/NEWS.md index 8b14a183d6..556361f388 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # ggplot2 (development version) +* Fixed bug in `width` computation when `position_dodge(preserve = "single")` + had duplicated `order` aesthetic values (@teunbrand, #6775). * The `arrow` and `arrow.fill` arguments are now available in `geom_linerange()` and `geom_pointrange()` layers (@teunbrand, #6481). * (internal) `zeroGrob()` now returns a `grid::nullGrob()` (#6390). diff --git a/R/position-dodge.R b/R/position-dodge.R index 9382bb2815..70d3419043 100644 --- a/R/position-dodge.R +++ b/R/position-dodge.R @@ -128,9 +128,10 @@ PositionDodge <- ggproto("PositionDodge", Position, n <- NULL } else { data$xmin <- data$xmin %||% data$x - cols <- intersect(colnames(data), c("group", "PANEL", "xmin")) + cols <- intersect(colnames(data), c("PANEL", "xmin")) + cols <- c(cols, if ("order" %in% names(data)) "order" else "group") n <- vec_unique(data[cols]) - n <- vec_group_id(n[setdiff(cols, "group")]) + n <- vec_group_id(n[setdiff(cols, c("group", "order"))]) n <- max(tabulate(n, attr(n, "n"))) } diff --git a/tests/testthat/test-position-dodge.R b/tests/testthat/test-position-dodge.R index 878ee6d155..36d2a92229 100644 --- a/tests/testthat/test-position-dodge.R +++ b/tests/testthat/test-position-dodge.R @@ -53,6 +53,18 @@ test_that("position_dodge() can use the order aesthetic", { expect_equal(ld$x, major + c(-0.2, 0, 0.2)[minor], ignore_attr = TRUE) }) +test_that("position_dodge() with duplicated order computes the correct width", { + df <- data_frame0( + group = c("A", "B", "C"), + order = c(1, 2, 2) + ) + ld <- layer_data( + ggplot(df, aes("X", 1, group = group, order = order)) + + geom_col(position = position_dodge(preserve = "single", width = 1), width = 1) + ) + expect_all_equal(ld$xmax - ld$xmin, 0.5) +}) + test_that("position_dodge warns about missing required aesthetics", { # Bit of a contrived geom to not have a required 'x' aesthetic