Skip to content

Commit 3d3b425

Browse files
authored
n.breaks are supplied to function-breaks. (#5974)
* deal with NA/NULL breaks earlier * generalise `trans_support_nbreaks()` --> `support_nbreaks()` * early exit on zero-range limits * apply `n.breaks` regarless or whence breaks-function came * Throw `NA` breaks error in 1 place * omit outdated comment * include binned scales * approve pattern snapshots (re: #6453) * add news bullet
1 parent 54d564d commit 3d3b425

9 files changed

+162
-233
lines changed

NEWS.md

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

3+
* In continuous scales, when `breaks` is a function and `n.breaks` is set, the
4+
`n.breaks` will be passed to the `breaks` function. Previously, `n.breaks`
5+
only applied to the default break calculation (@teunbrand, #5972)
36
* (internal) New `Facet$draw_panel_content()` method for delegating panel
47
assembly (@Yunuuuu, #6406).
58
* Facet gains a new method `setup_panel_params` to interact with the

R/scale-.R

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,12 @@ check_breaks_labels <- function(breaks, labels, call = NULL) {
640640
if (is.null(breaks) || is.null(labels)) {
641641
return(invisible())
642642
}
643+
if (identical(breaks, NA)) {
644+
cli::cli_abort(
645+
"Invalid {.arg breaks} specification. Use {.code NULL}, not {.code NA}.",
646+
call = call
647+
)
648+
}
643649

644650
bad_labels <- is.atomic(breaks) && is.atomic(labels) &&
645651
length(breaks) != length(labels)
@@ -751,48 +757,38 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale,
751757
return(numeric())
752758
}
753759
transformation <- self$get_transformation()
760+
breaks <- self$breaks %|W|% transformation$breaks
761+
762+
if (is.null(breaks)) {
763+
return(NULL)
764+
}
765+
754766
# Ensure limits don't exceed domain (#980)
755767
domain <- suppressWarnings(transformation$transform(transformation$domain))
756768
domain <- sort(domain)
757769
# To avoid NaN causing issues. NaN are dropped by the sort()
758770
if (length(domain) == 2 && !zero_range(domain)) {
759771
limits <- oob_squish(limits, domain)
760772
}
761-
762-
# Limits in transformed space need to be converted back to data space
763-
limits <- transformation$inverse(limits)
764-
765-
if (is.null(self$breaks)) {
766-
return(NULL)
767-
}
768-
769-
if (identical(self$breaks, NA)) {
770-
cli::cli_abort(
771-
"Invalid {.arg breaks} specification. Use {.code NULL}, not {.code NA}.",
772-
call = self$call
773-
)
773+
if (zero_range(as.numeric(limits))) {
774+
return(limits[1])
774775
}
775776

776-
# Compute `zero_range()` in transformed space in case `limits` in data space
777-
# don't support conversion to numeric (#5304)
778-
if (zero_range(as.numeric(transformation$transform(limits)))) {
779-
breaks <- limits[1]
780-
} else if (is.waiver(self$breaks)) {
781-
if (!is.null(self$n.breaks) && trans_support_nbreaks(transformation)) {
782-
breaks <- transformation$breaks(limits, self$n.breaks)
777+
if (is.function(breaks)) {
778+
# Limits in transformed space need to be converted back to data space
779+
limits <- transformation$inverse(limits)
780+
if (!is.null(self$n.breaks) && support_nbreaks(breaks)) {
781+
breaks <- breaks(limits, n = self$n.breaks)
783782
} else {
783+
breaks <- breaks(limits)
784784
if (!is.null(self$n.breaks)) {
785785
cli::cli_warn(
786-
"Ignoring {.arg n.breaks}. Use a {.cls transform} object that supports setting number of breaks.",
786+
"Ignoring {.arg n.breaks}. Use a {.cls transform} object or \\
787+
{.arg breaks} function that supports setting number of breaks",
787788
call = self$call
788789
)
789790
}
790-
breaks <- transformation$breaks(limits)
791791
}
792-
} else if (is.function(self$breaks)) {
793-
breaks <- self$breaks(limits)
794-
} else {
795-
breaks <- self$breaks
796792
}
797793

798794
# Breaks in data space need to be converted back to transformed space
@@ -1046,13 +1042,6 @@ ScaleDiscrete <- ggproto("ScaleDiscrete", Scale,
10461042
return(NULL)
10471043
}
10481044

1049-
if (identical(self$breaks, NA)) {
1050-
cli::cli_abort(
1051-
"Invalid {.arg breaks} specification. Use {.code NULL}, not {.code NA}.",
1052-
call = self$call
1053-
)
1054-
}
1055-
10561045
if (is.waiver(self$breaks)) {
10571046
breaks <- limits
10581047
} else if (is.function(self$breaks)) {
@@ -1268,14 +1257,9 @@ ScaleBinned <- ggproto("ScaleBinned", Scale,
12681257

12691258
if (is.null(self$breaks)) {
12701259
return(NULL)
1271-
} else if (identical(self$breaks, NA)) {
1272-
cli::cli_abort(
1273-
"Invalid {.arg breaks} specification. Use {.code NULL}, not {.code NA}.",
1274-
call = self$call
1275-
)
12761260
} else if (is.waiver(self$breaks)) {
12771261
if (self$nice.breaks) {
1278-
if (!is.null(self$n.breaks) && trans_support_nbreaks(transformation)) {
1262+
if (!is.null(self$n.breaks) && support_nbreaks(transformation$breaks)) {
12791263
breaks <- transformation$breaks(limits, n = self$n.breaks)
12801264
} else {
12811265
if (!is.null(self$n.breaks)) {
@@ -1332,9 +1316,16 @@ ScaleBinned <- ggproto("ScaleBinned", Scale,
13321316
}
13331317
}
13341318
} else if (is.function(self$breaks)) {
1335-
if ("n.breaks" %in% names(formals(environment(self$breaks)$f))) {
1319+
fmls <- names(formals(environment(self$breaks)$f))
1320+
if (any(c("n", "n.breaks") %in% fmls)) {
13361321
n.breaks <- self$n.breaks %||% 5 # same default as trans objects
1337-
breaks <- self$breaks(limits, n.breaks = n.breaks)
1322+
# TODO: we should only allow `n` argument and not `n.breaks` to be
1323+
# consistent with other scales. We should start deprecation at some point.
1324+
if ("n.breaks" %in% fmls) {
1325+
breaks <- self$breaks(limits, n.breaks = n.breaks)
1326+
} else {
1327+
breaks <- self$breaks(limits, n = n.breaks)
1328+
}
13381329
} else {
13391330
if (!is.null(self$n.breaks)) {
13401331
cli::cli_warn(
@@ -1439,6 +1430,14 @@ check_transformation <- function(x, transformed, name, arg = NULL, call = NULL)
14391430
cli::cli_warn(msg, call = call)
14401431
}
14411432

1433+
1434+
support_nbreaks <- function(fun) {
1435+
if (inherits(fun, "ggproto_method")) {
1436+
fun <- environment(fun)$f
1437+
}
1438+
"n" %in% fn_fmls_names(fun)
1439+
}
1440+
14421441
check_continuous_limits <- function(limits, ...,
14431442
arg = caller_arg(limits),
14441443
call = caller_env()) {
@@ -1449,10 +1448,6 @@ check_continuous_limits <- function(limits, ...,
14491448
check_length(limits, 2L, arg = arg, call = call)
14501449
}
14511450

1452-
trans_support_nbreaks <- function(trans) {
1453-
"n" %in% names(formals(trans$breaks))
1454-
}
1455-
14561451
allow_lambda <- function(x) {
14571452
if (is_formula(x)) as_function(x) else x
14581453
}

tests/testthat/_snaps/patterns/pattern-fills-no-alpha.svg

Lines changed: 18 additions & 12 deletions
Loading

0 commit comments

Comments
 (0)