Skip to content

Commit 4c1c8df

Browse files
authored
Allows breaks to be a function in geom_contour() (#4652)
1 parent 6e3ac81 commit 4c1c8df

File tree

6 files changed

+44
-14
lines changed

6 files changed

+44
-14
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
all `values` on the legend instead, use
99
`scale_*_manual(values = vals, limits = names(vals))`. (@teunbrand, @banfai,
1010
#4511, #4534)
11+
12+
* `geom_contour()` now accepts a function in the `breaks` argument (@eliocamp, #4652).
1113

1214
# ggplot2 3.3.5
1315
This is a very small release focusing on fixing a couple of untenable issues

R/geom-contour.r

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,14 @@
1919
#' @inheritParams geom_path
2020
#' @param bins Number of contour bins. Overridden by `binwidth`.
2121
#' @param binwidth The width of the contour bins. Overridden by `breaks`.
22-
#' @param breaks Numeric vector to set the contour breaks. Overrides `binwidth`
23-
#' and `bins`. By default, this is a vector of length ten with [pretty()]
24-
#' breaks.
22+
#' @param breaks One of:
23+
#' - Numeric vector to set the contour breaks
24+
#' - A function that takes the range of the data and binwidth as input
25+
#' and returns breaks as output. A function can be created from a formula
26+
#' (e.g. ~ fullseq(.x, .y)).
27+
#'
28+
#' Overrides `binwidth` and `bins`. By default, this is a vector of length
29+
#' ten with [pretty()] breaks.
2530
#' @seealso [geom_density_2d()]: 2d density contours
2631
#' @export
2732
#' @examples

R/stat-contour.r

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,17 @@ StatContourFilled <- ggproto("StatContourFilled", Stat,
144144
#' @noRd
145145
#'
146146
contour_breaks <- function(z_range, bins = NULL, binwidth = NULL, breaks = NULL) {
147-
if (!is.null(breaks)) {
147+
breaks <- allow_lambda(breaks)
148+
149+
if (is.numeric(breaks)) {
148150
return(breaks)
149151
}
150152

153+
breaks_fun <- fullseq
154+
if (is.function(breaks)) {
155+
breaks_fun <- breaks
156+
}
157+
151158
# If no parameters set, use pretty bins
152159
if (is.null(bins) && is.null(binwidth)) {
153160
breaks <- pretty(z_range, 10)
@@ -167,20 +174,20 @@ contour_breaks <- function(z_range, bins = NULL, binwidth = NULL, breaks = NULL)
167174
}
168175

169176
binwidth <- diff(z_range) / (bins - 1)
170-
breaks <- fullseq(z_range, binwidth)
177+
breaks <- breaks_fun(z_range, binwidth)
171178

172179
# Sometimes the above sequence yields one bin too few.
173180
# If this happens, try again.
174181
if (length(breaks) < bins + 1) {
175182
binwidth <- diff(z_range) / bins
176-
breaks <- fullseq(z_range, binwidth)
183+
breaks <- breaks_fun(z_range, binwidth)
177184
}
178185

179186
return(breaks)
180187
}
181188

182189
# if we haven't returned yet, compute breaks from binwidth
183-
fullseq(z_range, binwidth)
190+
breaks_fun(z_range, binwidth)
184191
}
185192

186193
#' Compute isoband objects

man/geom_contour.Rd

Lines changed: 10 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/geom_density_2d.Rd

Lines changed: 10 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-stat-contour.R

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,16 @@ test_that("contouring irregularly spaced data works", {
3232
expect_setequal(d8$y, c(2, 20/9, 16/9))
3333
})
3434

35-
test_that("contour breaks can be set manually and by bins and binwidth", {
35+
test_that("contour breaks can be set manually and by bins and binwidth and a function", {
3636
range <- c(0, 1)
3737
expect_equal(contour_breaks(range), pretty(range, 10))
3838
expect_identical(contour_breaks(range, breaks = 1:3), 1:3)
3939
expect_length(contour_breaks(range, bins = 5), 6)
4040
# shifting the range by 0.2 hits another execution branch in contour_breaks()
4141
expect_length(contour_breaks(range + 0.2, bins = 5), 6)
4242
expect_equal(resolution(contour_breaks(range, binwidth = 0.3)), 0.3)
43+
expect_equal(contour_breaks(range), contour_breaks(range, breaks = fullseq))
44+
expect_equal(contour_breaks(range), contour_breaks(range, breaks = ~fullseq(.x, .y)))
4345
})
4446

4547
test_that("geom_contour_filled() and stat_contour_filled() result in identical layer data", {

0 commit comments

Comments
 (0)