diff --git a/R/geom-bar.r b/R/geom-bar.r index 91d1767f3e..b1c7b5713f 100644 --- a/R/geom-bar.r +++ b/R/geom-bar.r @@ -118,6 +118,10 @@ GeomBar <- ggproto("GeomBar", GeomRect, non_missing_aes = c("xmin", "xmax", "ymin", "ymax"), setup_data = function(data, params) { + # Contrary to the case of geom_col(), the `width` in `data` is very likely + # a calculated column by Stat. So, geom_bar() should use data$width if + # available. Note that StatIdentity is not the case, but, as we cannot know + # what Stat was used, we can do nothing here. data$width <- data$width %||% params$width %||% (resolution(data$x, FALSE) * 0.9) transform(data, diff --git a/R/geom-col.r b/R/geom-col.r index 7ebd51f8fc..22f2fdd399 100644 --- a/R/geom-col.r +++ b/R/geom-col.r @@ -38,8 +38,11 @@ GeomCol <- ggproto("GeomCol", GeomRect, non_missing_aes = c("xmin", "xmax", "ymin", "ymax"), setup_data = function(data, params) { - data$width <- data$width %||% - params$width %||% (resolution(data$x, FALSE) * 0.9) + # To ensure bar widths are constant within a PANEL, `width` is not allowed + # to be mapped to data. So, even if the `data` already contains `width`, it + # should be ignored except when the width is calculated by Stat. But, as + # geom_col() uses stat_identity() fixedly, this is not the case. + data$width <- params$width %||% (resolution(data$x, FALSE) * 0.9) transform(data, ymin = pmin(y, 0), ymax = pmax(y, 0), xmin = x - width / 2, xmax = x + width / 2, width = NULL diff --git a/tests/testthat/test-geom-col.R b/tests/testthat/test-geom-col.R index ed10be1883..12335837c6 100644 --- a/tests/testthat/test-geom-col.R +++ b/tests/testthat/test-geom-col.R @@ -14,3 +14,12 @@ test_that("geom_col removes columns with parts outside the plot limits", { "Removed 1 rows containing missing values" ) }) + +test_that("geom_col() ignores width", { + dat <- data_frame(x = c(1, 2, 3)) + + + p <- ggplot(dat, aes(x, x, width = x)) + geom_col() + d <- layer_data(p) + expect_equal(d$xmax - d$xmin, c(0.9, 0.9, 0.9)) +})