Skip to content

Feat/issue 4899 simplify alignment for column geoms #4921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# ggplot2 (development version)

* `geom_col()` and `geom_bar()` gain a new `just` argument. This is set to `0.5`
by default; use `just = 0`/`just = 1` to place columns on the left/right
of the axis breaks.
(@wurli, #4899)

* Fix a bug in `position_jitter()` where infinity values were dropped (@javlon,
#4790).

Expand All @@ -14,6 +19,7 @@
columns were dropped and warns about this. If stats intend to drop
data columns they can declare them in the new field `dropped_aes`.
(@clauswilke, #3250)

* Added `stat_align()` to align data without common x-coordinates prior to
stacking. This is now the default stat for `geom_area()` (@thomasp85, #4850)

Expand Down
23 changes: 20 additions & 3 deletions R/geom-bar.r
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@
#' automatically determines the orientation from the aesthetic mapping. In the
#' rare event that this fails it can be given explicitly by setting `orientation`
#' to either `"x"` or `"y"`. See the *Orientation* section for more detail.
#' @param width Bar width. By default, set to 90% of the resolution of the data.
#' @param just Adjustment for column placement. Set to `0.5` by default, meaning
#' that columns will be centered about axis breaks. Set to `0` or `1` to place
#' columns to the left/right of axis breaks. Note that this argument may have
#' unintended behaviour when used with alternative positions, e.g.
#' `position_dodge()`.
#' @param width Bar width. By default, set to 90% of the [resolution()] of the
#' data.
#' @param geom,stat Override the default connection between `geom_bar()` and
#' `stat_count()`.
#' @examples
Expand Down Expand Up @@ -80,9 +86,17 @@
#' ggplot(df, aes(x)) + geom_bar()
#' # cf. a histogram of the same data
#' ggplot(df, aes(x)) + geom_histogram(binwidth = 0.5)
#'
#' # Use `just` to control how columns are aligned with axis breaks:
#' df <- data.frame(x = as.Date(c("2020-01-01", "2020-02-01")), y = 1:2)
#' # Columns centered on the first day of the month
#' ggplot(df, aes(x, y)) + geom_col(just = 0.5)
#' # Columns begin on the first day of the month
#' ggplot(df, aes(x, y)) + geom_col(just = 1)
geom_bar <- function(mapping = NULL, data = NULL,
stat = "count", position = "stack",
...,
just = 0.5,
width = NULL,
na.rm = FALSE,
orientation = NA,
Expand All @@ -97,6 +111,7 @@ geom_bar <- function(mapping = NULL, data = NULL,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list2(
just = just,
width = width,
na.rm = na.rm,
orientation = orientation,
Expand All @@ -123,16 +138,18 @@ GeomBar <- ggproto("GeomBar", GeomRect,
params
},

extra_params = c("na.rm", "orientation"),
extra_params = c("just", "na.rm", "orientation"),

setup_data = function(data, params) {
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)
data$just <- params$just %||% 0.5
data <- transform(data,
ymin = pmin(y, 0), ymax = pmax(y, 0),
xmin = x - width / 2, xmax = x + width / 2, width = NULL
xmin = x - width * (1 - just), xmax = x + width * just,
width = NULL, just = NULL
)
flip_data(data, params$flipped_aes)
},
Expand Down
13 changes: 9 additions & 4 deletions R/geom-col.r
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
geom_col <- function(mapping = NULL, data = NULL,
position = "stack",
...,
just = 0.5,
width = NULL,
na.rm = FALSE,
show.legend = NA,
Expand All @@ -17,6 +18,7 @@ geom_col <- function(mapping = NULL, data = NULL,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list2(
just = just,
width = width,
na.rm = na.rm,
...
Expand All @@ -42,16 +44,19 @@ GeomCol <- ggproto("GeomCol", GeomRect,
params
},

extra_params = c("na.rm", "orientation"),
extra_params = c("just", "na.rm", "orientation"),

setup_data = function(data, params) {
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)
data <- transform(data,
ymin = pmin(y, 0), ymax = pmax(y, 0),
xmin = x - width / 2, xmax = x + width / 2, width = NULL
data$just <- params$just %||% 0.5
data <- transform(
data,
ymin = pmin(y, 0), ymax = pmax(y, 0),
xmin = x - width * (1 - just), xmax = x + width * just,
width = NULL, just = NULL
)
flip_data(data, params$flipped_aes)
},
Expand Down
18 changes: 17 additions & 1 deletion man/geom_bar.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions tests/testthat/test-geom-col.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,22 @@ test_that("geom_col works in both directions", {
y$flipped_aes <- NULL
expect_identical(x, flip_data(y, TRUE)[,names(x)])
})

test_that("geom_col supports alignment of columns", {
dat <- data_frame(x = c("a", "b"), y = c(1.2, 2.5))

p <- ggplot(dat, aes(x, y)) + geom_col(just = 0.5)
y <- layer_data(p)
expect_equal(as.numeric(y$xmin), c(0.55, 1.55))
expect_equal(as.numeric(y$xmax), c(1.45, 2.45))

p <- ggplot(dat, aes(x, y)) + geom_col(just = 0.0)
y <- layer_data(p)
expect_equal(as.numeric(y$xmin), c(0.1, 1.1))
expect_equal(as.numeric(y$xmax), c(1.0, 2.0))

p <- ggplot(dat, aes(x, y)) + geom_col(just = 1.0)
y <- layer_data(p)
expect_equal(as.numeric(y$xmin), c(1.0, 2.0))
expect_equal(as.numeric(y$xmax), c(1.9, 2.9))
})