Skip to content

Commit cd7199d

Browse files
authored
Binned limits and reverse transform (#5357)
* Borrow `get_limits()` method * Consider sort-order of limits * Add tests * Add news bullet
1 parent a747da3 commit cd7199d

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

NEWS.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
# ggplot2 (development version)
22

3+
* Binned scales now treat `NA`s in limits the same way continuous scales do
4+
(#5355).
5+
6+
* Binned scales work better with `trans = "reverse"` (#5355).
7+
38
* The `legend.text.align` and `legend.title.align` arguments in `theme()` are
49
deprecated. The `hjust` setting of the `legend.text` and `legend.title`
510
elements continues to fulfil the role of text alignment (@teunbrand, #5347).
611

712
* Integers are once again valid input to theme arguments that expect numeric
813
input (@teunbrand, #5369)
914

10-
1115
* Nicer error messages for xlim/ylim arguments in coord-* functions
1216
(@92amartins, #4601, #5297).
1317

R/scale-.R

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,10 +1057,16 @@ ScaleBinned <- ggproto("ScaleBinned", Scale,
10571057
expand_range4(self$get_limits(), expand)
10581058
},
10591059

1060+
get_limits = function(self) {
1061+
ggproto_parent(ScaleContinuous, self)$get_limits()
1062+
},
1063+
10601064
get_breaks = function(self, limits = self$get_limits()) {
10611065
if (self$is_empty()) return(numeric())
10621066

10631067
limits <- self$trans$inverse(limits)
1068+
is_rev <- limits[2] < limits[1]
1069+
limits <- sort(limits)
10641070

10651071
if (is.null(self$breaks)) {
10661072
return(NULL)
@@ -1107,7 +1113,11 @@ ScaleBinned <- ggproto("ScaleBinned", Scale,
11071113
}
11081114
new_limits_trans <- suppressWarnings(self$trans$transform(new_limits))
11091115
limits[is.finite(new_limits_trans)] <- new_limits[is.finite(new_limits_trans)]
1110-
self$limits <- self$trans$transform(limits)
1116+
if (is_rev) {
1117+
self$limits <- rev(self$trans$transform(limits))
1118+
} else {
1119+
self$limits <- self$trans$transform(limits)
1120+
}
11111121
}
11121122
} else if (is.function(self$breaks)) {
11131123
if ("n.breaks" %in% names(formals(environment(self$breaks)$f))) {
@@ -1124,7 +1134,8 @@ ScaleBinned <- ggproto("ScaleBinned", Scale,
11241134
}
11251135

11261136
# Breaks must be within limits
1127-
breaks <- breaks[breaks >= limits[1] & breaks <= limits[2]]
1137+
breaks <- oob_discard(breaks, sort(limits))
1138+
11281139
self$breaks <- breaks
11291140

11301141
self$trans$transform(breaks)

tests/testthat/test-scale-binned.R

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ test_that("binned limits should not compute out-of-bounds breaks", {
4444
))
4545
})
4646

47+
test_that("binned scales can use NAs in limits", {
48+
scale <- scale_x_binned(limits = c(NA, 10))
49+
scale$train(c(-20, 20))
50+
expect_equal(scale$get_limits(), c(-20, 10))
51+
scale <- scale_x_binned(limits = c(-10, NA))
52+
scale$train(c(-20, 20))
53+
expect_equal(scale$get_limits(), c(-10, 20))
54+
})
55+
56+
test_that("binned scales can calculate breaks with reverse transformation", {
57+
scale <- scale_x_binned(trans = "reverse")
58+
scale$train(c(1, 9))
59+
expect_equal(scale$get_breaks(), 8:2)
60+
})
61+
4762
test_that('binned scales can calculate breaks on dates', {
4863

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

0 commit comments

Comments
 (0)