Skip to content

Commit 5e388e1

Browse files
authored
Implement n_breaks in continuous_scale (#3102)
1 parent 0c997f1 commit 5e388e1

7 files changed

+80
-33
lines changed

NEWS.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# ggplot2 (development version)
22

3+
* `scale_x_continuous()` and `scale_y_continuous()` gains an `n.breaks` argument
4+
guiding the number of automatic generated breaks (@thomasp85, #3102)
5+
36
* `geom_sf()` now removes rows that can't be plotted due to `NA` aesthetics
47
(#3546, @thomasp85)
58

R/scale-.r

+28-9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
#' each major break)
2626
#' - A numeric vector of positions
2727
#' - A function that given the limits returns a vector of minor breaks.
28+
#' @param n.breaks An integer guiding the number of major breaks. The algorithm
29+
#' may choose a slightly different number to ensure nice break labels. Will
30+
#' only have an effect if `breaks = waiver()`. Use `NULL` to use the default
31+
#' number of breaks given by the transformation.
2832
#' @param labels One of:
2933
#' - `NULL` for no labels
3034
#' - `waiver()` for the default labels computed by the
@@ -78,9 +82,11 @@
7882
#' @param super The super class to use for the constructed scale
7983
#' @keywords internal
8084
continuous_scale <- function(aesthetics, scale_name, palette, name = waiver(),
81-
breaks = waiver(), minor_breaks = waiver(), labels = waiver(), limits = NULL,
82-
rescaler = rescale, oob = censor, expand = waiver(), na.value = NA_real_,
83-
trans = "identity", guide = "legend", position = "left", super = ScaleContinuous) {
85+
breaks = waiver(), minor_breaks = waiver(), n.breaks = NULL,
86+
labels = waiver(), limits = NULL, rescaler = rescale,
87+
oob = censor, expand = waiver(), na.value = NA_real_,
88+
trans = "identity", guide = "legend", position = "left",
89+
super = ScaleContinuous) {
8490

8591
aesthetics <- standardise_aes_names(aesthetics)
8692

@@ -116,6 +122,7 @@ continuous_scale <- function(aesthetics, scale_name, palette, name = waiver(),
116122
name = name,
117123
breaks = breaks,
118124
minor_breaks = minor_breaks,
125+
n.breaks = n.breaks,
119126

120127
labels = labels,
121128
guide = guide,
@@ -524,6 +531,7 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale,
524531
rescaler = rescale,
525532
oob = censor,
526533
minor_breaks = waiver(),
534+
n.breaks = NULL,
527535

528536
is_discrete = function() FALSE,
529537

@@ -535,10 +543,10 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale,
535543
},
536544

537545
transform = function(self, x) {
538-
new_x <- self$trans$transform(x)
539-
axis <- if ("x" %in% self$aesthetics) "x" else "y"
540-
check_transformation(x, new_x, self$scale_name, axis)
541-
new_x
546+
new_x <- self$trans$transform(x)
547+
axis <- if ("x" %in% self$aesthetics) "x" else "y"
548+
check_transformation(x, new_x, self$scale_name, axis)
549+
new_x
542550
},
543551

544552
map = function(self, x, limits = self$get_limits()) {
@@ -578,7 +586,14 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale,
578586
if (zero_range(as.numeric(limits))) {
579587
breaks <- limits[1]
580588
} else if (is.waive(self$breaks)) {
581-
breaks <- self$trans$breaks(limits)
589+
if (!is.null(self$n.breaks) && trans_support_nbreaks(self$trans)) {
590+
breaks <- self$trans$breaks(limits, self$n.breaks)
591+
} else {
592+
if (!is.null(self$n.breaks)) {
593+
warning("Ignoring n.breaks. Use a trans object that supports setting number of breaks", call. = FALSE)
594+
}
595+
breaks <- self$trans$breaks(limits)
596+
}
582597
} else if (is.function(self$breaks)) {
583598
breaks <- self$breaks(limits)
584599
} else {
@@ -952,7 +967,7 @@ ScaleBinned <- ggproto("ScaleBinned", Scale,
952967
stop("Invalid breaks specification. Use NULL, not NA", call. = FALSE)
953968
} else if (is.waive(self$breaks)) {
954969
if (self$nice.breaks) {
955-
if (!is.null(self$n.breaks) && "n" %in% names(formals(self$trans$breaks))) {
970+
if (!is.null(self$n.breaks) && trans_support_nbreaks(self$trans)) {
956971
breaks <- self$trans$breaks(limits, n = self$n.breaks)
957972
} else {
958973
if (!is.null(self$n.breaks)) {
@@ -1090,3 +1105,7 @@ check_transformation <- function(x, transformed, name, axis) {
10901105
warning("Transformation introduced infinite values in ", type, " ", axis, "-axis", call. = FALSE)
10911106
}
10921107
}
1108+
1109+
trans_support_nbreaks <- function(trans) {
1110+
"n" %in% names(formals(trans$breaks))
1111+
}

R/scale-continuous.r

+14-10
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,15 @@ NULL
7474
#'
7575
#' @export
7676
scale_x_continuous <- function(name = waiver(), breaks = waiver(),
77-
minor_breaks = waiver(), labels = waiver(),
78-
limits = NULL, expand = waiver(), oob = censor,
79-
na.value = NA_real_, trans = "identity", guide = waiver(),
80-
position = "bottom", sec.axis = waiver()) {
77+
minor_breaks = waiver(), n.breaks = NULL,
78+
labels = waiver(), limits = NULL,
79+
expand = waiver(), oob = censor,
80+
na.value = NA_real_, trans = "identity",
81+
guide = waiver(), position = "bottom",
82+
sec.axis = waiver()) {
8183
sc <- continuous_scale(
8284
c("x", "xmin", "xmax", "xend", "xintercept", "xmin_final", "xmax_final", "xlower", "xmiddle", "xupper", "x0"),
83-
"position_c", identity, name = name, breaks = breaks,
85+
"position_c", identity, name = name, breaks = breaks, n.breaks = n.breaks,
8486
minor_breaks = minor_breaks, labels = labels, limits = limits,
8587
expand = expand, oob = oob, na.value = na.value, trans = trans,
8688
guide = guide, position = position, super = ScaleContinuousPosition
@@ -93,13 +95,15 @@ scale_x_continuous <- function(name = waiver(), breaks = waiver(),
9395
#' @rdname scale_continuous
9496
#' @export
9597
scale_y_continuous <- function(name = waiver(), breaks = waiver(),
96-
minor_breaks = waiver(), labels = waiver(),
97-
limits = NULL, expand = waiver(), oob = censor,
98-
na.value = NA_real_, trans = "identity", guide = waiver(),
99-
position = "left", sec.axis = waiver()) {
98+
minor_breaks = waiver(), n.breaks = NULL,
99+
labels = waiver(), limits = NULL,
100+
expand = waiver(), oob = censor,
101+
na.value = NA_real_, trans = "identity",
102+
guide = waiver(), position = "left",
103+
sec.axis = waiver()) {
100104
sc <- continuous_scale(
101105
c("y", "ymin", "ymax", "yend", "yintercept", "ymin_final", "ymax_final", "lower", "middle", "upper", "y0"),
102-
"position_c", identity, name = name, breaks = breaks,
106+
"position_c", identity, name = name, breaks = breaks, n.breaks = n.breaks,
103107
minor_breaks = minor_breaks, labels = labels, limits = limits,
104108
expand = expand, oob = oob, na.value = na.value, trans = trans,
105109
guide = guide, position = position, super = ScaleContinuousPosition

man/continuous_scale.Rd

+10-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/scale_continuous.Rd

+13-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/scale_gradient.Rd

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/scale_size.Rd

+8-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)