Skip to content

Commit c9b85d6

Browse files
authored
Merge pull request #5104 from teunbrand/binned_limits
Iron out binned limits and breaks
2 parents bee7034 + 77f6aaf commit c9b85d6

File tree

4 files changed

+43
-0
lines changed

4 files changed

+43
-0
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# ggplot2 (development version)
22

3+
* Automatic breaks in `scale_*_binned()` should no longer be out-of-bounds,
4+
and automatic limits expand to include these (@teunbrand, #5095, #5100).
35
* Renamed computed aesthetic in `stat_ecdf()` to `ecdf`, to prevent incorrect
46
scale transformations (@teunbrand, #5113 and #5112).
57
* Fixed misbehaviour of `draw_key_boxplot()` and `draw_key_crossbar()` with

R/scale-.r

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,7 @@ ScaleBinned <- ggproto("ScaleBinned", Scale,
10771077
breaks <- seq(limits[1], limits[2], length.out = n.breaks + 2)
10781078
breaks <- breaks[-c(1, length(breaks))]
10791079
}
1080+
breaks <- oob_discard(breaks, limits)
10801081

10811082
# Ensure terminal bins are same width if limits not set
10821083
if (is.null(self$limits)) {

R/scale-binned.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ ScaleBinnedPosition <- ggproto("ScaleBinnedPosition", ScaleBinned,
7070

7171
map = function(self, x, limits = self$get_limits()) {
7272
breaks <- self$get_breaks(limits)
73+
limits <- self$get_limits() # get_breaks() may have updated this
7374
all_breaks <- unique0(sort(c(limits[1], breaks, limits[2])))
7475

7576
if (self$after.stat) {

tests/testthat/test-scale-binned.R

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,45 @@ test_that("binned scales only support continuous data", {
55
expect_snapshot_error(ggplot_build(p))
66
})
77

8+
test_that("binned scales limits can expand to fit breaks", {
9+
# See also #5095
10+
11+
scale <- scale_x_binned(right = FALSE, show.limits = TRUE)
12+
scale$train(c(14, 29))
13+
14+
limits <- scale$get_limits()
15+
breaks <- scale$get_breaks()
16+
new_limits <- scale$get_limits()
17+
18+
# Positive control
19+
expect_equal(limits, c(14, 29))
20+
# Test case, should have been updated in break calculation
21+
expect_equal(new_limits, c(14, 30))
22+
23+
# Negative control
24+
# Now, new limits should not be updated because limits were given instead
25+
# of computed
26+
scale <- scale_x_binned(right = FALSE, show.limits = TRUE,
27+
limits = c(14, 29))
28+
limits <- scale$get_limits()
29+
breaks <- scale$get_breaks()
30+
new_limits <- scale$get_limits()
31+
32+
expect_equal(limits, new_limits)
33+
})
34+
35+
test_that("binned limits should not compute out-of-bounds breaks", {
36+
scale <- scale_x_binned(n.breaks = 10)
37+
scale$train(c(1, 9))
38+
39+
limits <- scale$get_limits()
40+
breaks <- scale$get_breaks()
41+
expect_length(breaks, 7) # Not the requested 10 due to oob discarding
42+
expect_true(all(
43+
breaks > limits[1] & breaks < limits[2]
44+
))
45+
})
46+
847
test_that('binned scales can calculate breaks on dates', {
948

1049
data <- seq(as.Date("2000-01-01"), as.Date("2020-01-01"), length.out = 100)

0 commit comments

Comments
 (0)