diff --git a/NEWS.md b/NEWS.md index e99235a3a0..d553c7f924 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # ggplot2 (development version) +* `stat_bin()` now accepts functions for argument `breaks` (@aijordan, #4561) * (internal) The plot's layout now has a coord parameter that is used to prevent setting up identical panel parameters (#5427) * (internal) rearranged the code of `Facet$draw_panels()` method (@teunbrand). diff --git a/R/stat-bin.R b/R/stat-bin.R index 4f35d83a84..4c00b2e3ab 100644 --- a/R/stat-bin.R +++ b/R/stat-bin.R @@ -22,7 +22,7 @@ #' outside the range of the data. #' @param breaks Alternatively, you can supply a numeric vector giving #' the bin boundaries. Overrides `binwidth`, `bins`, `center`, -#' and `boundary`. +#' and `boundary`. Can also be a function that takes group-wise values as input and returns bin boundaries. #' @param closed One of `"right"` or `"left"` indicating whether right #' or left edges of bins are included in the bin. #' @param pad If `TRUE`, adds empty bins at either end of x. This ensures @@ -146,6 +146,9 @@ StatBin <- ggproto("StatBin", Stat, origin = NULL, right = NULL, drop = NULL) { x <- flipped_names(flipped_aes)$x if (!is.null(breaks)) { + if (is.function(breaks)) { + breaks <- breaks(data[[x]]) + } if (!scales[[x]]$is_discrete()) { breaks <- scales[[x]]$transform(breaks) } diff --git a/man/geom_histogram.Rd b/man/geom_histogram.Rd index 7cd907daed..f60ec4b1f5 100644 --- a/man/geom_histogram.Rd +++ b/man/geom_histogram.Rd @@ -164,7 +164,7 @@ outside the range of the data.} \item{breaks}{Alternatively, you can supply a numeric vector giving the bin boundaries. Overrides \code{binwidth}, \code{bins}, \code{center}, -and \code{boundary}.} +and \code{boundary}. Can also be a function that takes group-wise values as input and returns bin boundaries.} \item{closed}{One of \code{"right"} or \code{"left"} indicating whether right or left edges of bins are included in the bin.} diff --git a/tests/testthat/test-stat-bin.R b/tests/testthat/test-stat-bin.R index af0ae467f3..9b55054604 100644 --- a/tests/testthat/test-stat-bin.R +++ b/tests/testthat/test-stat-bin.R @@ -60,6 +60,14 @@ test_that("can use breaks argument", { expect_equal(out$count, c(1, 2)) }) +test_that("breaks computes bin boundaries for function input", { + df <- data.frame(x = c(0, 0, 0, 1:3)) + out <- layer_data(ggplot(df, aes(x)) + + geom_histogram(breaks = function(x) c(0, 0.5, 2.5, 7.5))) + + expect_equal(out$count, c(3, 2, 1)) +}) + test_that("fuzzy breaks are used when cutting", { df <- data_frame(x = c(-1, -0.5, -0.4, 0)) p <- ggplot(df, aes(x)) +