Skip to content

Commit 917045a

Browse files
committed
centralise argument checking in compute_bins()
1 parent bb65b8e commit 917045a

File tree

5 files changed

+39
-70
lines changed

5 files changed

+39
-70
lines changed

R/bin.R

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,12 @@ bin_breaks <- function(breaks, closed = c("right", "left")) {
5454

5555
bin_breaks_width <- function(x_range, width = NULL, center = NULL,
5656
boundary = NULL, closed = c("right", "left")) {
57-
check_length(x_range, 2L)
5857

59-
# binwidth seems to be the argument name supplied to width. (stat-bin and stat-bindot)
60-
check_number_decimal(width, min = 0, allow_infinite = FALSE, arg = "binwidth")
61-
62-
if (!is.null(boundary) && !is.null(center)) {
63-
cli::cli_abort("Only one of {.arg boundary} and {.arg center} may be specified.")
64-
} else if (is.null(boundary)) {
58+
if (is.null(boundary)) {
6559
if (is.null(center)) {
6660
# If neither edge nor center given, compute both using tile layer's
6761
# algorithm. This puts min and max of data in outer half of their bins.
6862
boundary <- width / 2
69-
7063
} else {
7164
# If center given but not boundary, compute boundary.
7265
boundary <- center - width / 2
@@ -75,9 +68,6 @@ bin_breaks_width <- function(x_range, width = NULL, center = NULL,
7568

7669
# Find the left side of left-most bin: inputs could be Dates or POSIXct, so
7770
# coerce to numeric first.
78-
x_range <- as.numeric(x_range)
79-
width <- as.numeric(width)
80-
boundary <- as.numeric(boundary)
8171
shift <- floor((x_range[1] - boundary) / width)
8272
origin <- boundary + shift * width
8373

@@ -104,9 +94,7 @@ bin_breaks_width <- function(x_range, width = NULL, center = NULL,
10494

10595
bin_breaks_bins <- function(x_range, bins = 30, center = NULL,
10696
boundary = NULL, closed = c("right", "left")) {
107-
check_length(x_range, 2L)
10897

109-
check_number_whole(bins, min = 1)
11098
if (zero_range(x_range)) {
11199
# 0.1 is the same width as the expansion `default_expansion()` gives for 0-width data
112100
width <- 0.1
@@ -128,27 +116,38 @@ bin_breaks_bins <- function(x_range, bins = 30, center = NULL,
128116

129117
# Compute bins ------------------------------------------------------------
130118

131-
compute_bins <- function(x, scale, breaks = NULL, binwidth = NULL, bins = NULL,
119+
compute_bins <- function(x, scale = NULL, breaks = NULL, binwidth = NULL, bins = NULL,
132120
center = NULL, boundary = NULL,
133121
closed = c("right", "left")) {
134122

123+
range <- if (is.scale(scale)) scale$dimension() else range(x)
124+
check_length(range, 2L)
125+
135126
if (!is.null(breaks)) {
136127
if (is.function(breaks)) {
137128
breaks <- breaks(x)
138129
}
139-
if (!scale$is_discrete()) {
130+
if (is.scale(scale) && !scale$is_discrete()) {
140131
breaks <- scale$transform(breaks)
141132
}
133+
check_numeric(breaks)
142134
bins <- bin_breaks(breaks, closed)
143135
return(bins)
144136
}
145137

138+
check_number_decimal(boundary, allow_infinite = FALSE, allow_null = TRUE)
139+
check_number_decimal(center, allow_infinite = FALSE, allow_null = TRUE)
140+
if (!is.null(boundary) && !is.null(center)) {
141+
cli::cli_abort("Only one of {.arg boundary} and {.arg center} may be specified.")
142+
}
143+
146144
if (!is.null(binwidth)) {
147145
if (is.function(binwidth)) {
148146
binwidth <- binwidth(x)
149147
}
148+
check_number_decimal(binwidth, min = 0, allow_infinite = FALSE)
150149
bins <- bin_breaks_width(
151-
scale$dimension(), binwidth,
150+
range, binwidth,
152151
center = center, boundary = boundary, closed = closed
153152
)
154153
return(bins)
@@ -157,8 +156,9 @@ compute_bins <- function(x, scale, breaks = NULL, binwidth = NULL, bins = NULL,
157156
if (is.function(bins)) {
158157
bins <- bins(x)
159158
}
159+
check_number_whole(bins, min = 1, allow_infinite = FALSE)
160160
bin_breaks_bins(
161-
scale$dimension(), bins,
161+
range, bins,
162162
center = center, boundary = boundary, closed = closed
163163
)
164164
}
@@ -253,13 +253,6 @@ fix_bin_params = function(params, fun, version) {
253253
params$right <- NULL
254254
}
255255

256-
if (!is.null(params$boundary) && !is.null(params$center)) {
257-
cli::cli_abort(
258-
"Only one of {.arg boundary} and {.arg center} may be specified \\
259-
in {.fn {fun}}."
260-
)
261-
}
262-
263256
if (is.null(params$breaks %||% params$binwidth %||% params$bins)) {
264257
cli::cli_inform(
265258
"{.fn {fun}} using {.code bins = 30}. Pick better value {.arg binwidth}."

tests/testthat/_snaps/stat-bin.md

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,51 +23,30 @@
2323

2424
# inputs to binning are checked
2525

26-
Computation failed in `stat_bin()`.
27-
Caused by error in `bins()`:
28-
! `breaks` must be a <numeric> vector, not a character vector.
26+
`breaks` must be a <numeric> vector, not a character vector.
2927

3028
---
3129

32-
`x_range` must be a vector of length 2, not length 1.
30+
`binwidth` must be a number, not a character vector.
3331

3432
---
3533

36-
Computation failed in `stat_bin()`.
37-
Caused by error in `bin_breaks_width()`:
38-
! `binwidth` must be a number, not a character vector.
34+
`binwidth` must be a number larger than or equal to 0, not the number -4.
3935

4036
---
4137

42-
Computation failed in `stat_bin()`.
43-
Caused by error in `bin_breaks_width()`:
44-
! `binwidth` must be a number larger than or equal to 0, not the number -4.
45-
46-
---
47-
48-
`x_range` must be a vector of length 2, not length 1.
49-
50-
---
51-
52-
Computation failed in `stat_bin()`.
53-
Caused by error in `bin_breaks_bins()`:
54-
! `bins` must be a whole number larger than or equal to 1, not the number -4.
38+
`bins` must be a whole number larger than or equal to 1, not the number -4.
5539

5640
# setting boundary and center
5741

58-
Code
59-
comp_bin(df, boundary = 5, center = 0)
60-
Condition
61-
Error in `stat_bin()`:
62-
! Problem while computing stat.
63-
i Error occurred in the 1st layer.
64-
Caused by error in `fix_bin_params()`:
65-
! Only one of `boundary` and `center` may be specified in `stat_bin()`.
42+
Computation failed in `stat_bin()`.
43+
Caused by error in `compute_bins()`:
44+
! Only one of `boundary` and `center` may be specified.
6645

6746
# bin errors at high bin counts
6847

6948
Code
70-
bin_breaks_width(c(1, 2e+06), 1)
49+
compute_bins(c(1, 2e+06), binwidth = 1)
7150
Condition
7251
Error in `bin_breaks_width()`:
7352
! The number of histogram bins must be less than 1,000,000.

tests/testthat/_snaps/stat-bin2d.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# binwidth is respected
22

33
Computation failed in `stat_bin2d()`.
4-
Caused by error in `bin2d_breaks()`:
4+
Caused by error in `compute_bins()`:
55
! `binwidth` must be a number, not a double vector.
66

77
---
88

99
Computation failed in `stat_bin2d()`.
10-
Caused by error in `bin2d_breaks()`:
11-
! `origin` must be a number, not a double vector.
10+
Caused by error in `compute_bins()`:
11+
! `boundary` must be a number or `NULL`, not a double vector.
1212

tests/testthat/test-stat-bin.R

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -147,19 +147,19 @@ test_that("bins is strictly adhered to", {
147147

148148
# Default case
149149
nbreaks <- vapply(nbins, function(bins) {
150-
length(bin_breaks_bins(c(0, 10), bins)$breaks)
150+
length(compute_bins(c(0, 10), bins = bins)$breaks)
151151
}, numeric(1))
152152
expect_equal(nbreaks, nbins + 1)
153153

154154
# Center is provided
155155
nbreaks <- vapply(nbins, function(bins) {
156-
length(bin_breaks_bins(c(0, 10), bins, center = 0)$breaks)
156+
length(compute_bins(c(0, 10), bins = bins, center = 0)$breaks)
157157
}, numeric(1))
158158
expect_equal(nbreaks, nbins + 1)
159159

160160
# Boundary is provided
161161
nbreaks <- vapply(nbins, function(bins) {
162-
length(bin_breaks_bins(c(0, 10), bins, boundary = 0)$breaks)
162+
length(compute_bins(c(0, 10), bins = bins, boundary = 0)$breaks)
163163
}, numeric(1))
164164
expect_equal(nbreaks, nbins + 1)
165165

@@ -172,13 +172,10 @@ comp_bin <- function(df, ...) {
172172

173173
test_that("inputs to binning are checked", {
174174
dat <- data_frame(x = c(0, 10))
175-
expect_snapshot_error(comp_bin(dat, breaks = letters))
176-
expect_snapshot_error(bin_breaks_width(3))
177-
expect_snapshot_error(comp_bin(dat, binwidth = letters))
178-
expect_snapshot_error(comp_bin(dat, binwidth = -4))
179-
180-
expect_snapshot_error(bin_breaks_bins(3))
181-
expect_snapshot_error(comp_bin(dat, bins = -4))
175+
expect_snapshot_error(compute_bins(dat, breaks = letters))
176+
expect_snapshot_error(compute_bins(dat, binwidth = letters))
177+
expect_snapshot_error(compute_bins(dat, binwidth = -4))
178+
expect_snapshot_error(compute_bins(dat, bins = -4))
182179
})
183180

184181
test_that("closed left or right", {
@@ -208,14 +205,14 @@ test_that("setting boundary and center", {
208205
df <- data_frame(x = c(0, 30))
209206

210207
# Error if both boundary and center are specified
211-
expect_snapshot(comp_bin(df, boundary = 5, center = 0), error = TRUE)
208+
expect_snapshot_warning(comp_bin(df, boundary = 5, center = 0, bins = 30))
212209

213210
res <- comp_bin(df, binwidth = 10, boundary = 0, pad = FALSE)
214211
expect_identical(res$count, c(1, 0, 1))
215212
expect_identical(res$xmin[1], 0)
216213
expect_identical(res$xmax[3], 30)
217214

218-
res <- comp_bin(df, binwidth = 10, center = 0, pad = FALSE)
215+
res <- comp_bin(df, binwidth = 10, center = 0, boundary = NULL, pad = FALSE)
219216
expect_identical(res$count, c(1, 0, 0, 1))
220217
expect_identical(res$xmin[1], df$x[1] - 5)
221218
expect_identical(res$xmax[4], df$x[2] + 5)
@@ -230,7 +227,7 @@ test_that("weights are added", {
230227
})
231228

232229
test_that("bin errors at high bin counts", {
233-
expect_snapshot(bin_breaks_width(c(1, 2e6), 1), error = TRUE)
230+
expect_snapshot(compute_bins(c(1, 2e6), binwidth = 1), error = TRUE)
234231
})
235232

236233
# stat_count --------------------------------------------------------------

tests/testthat/test-stat-bin2d.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ test_that("binwidth is respected", {
1414
expect_snapshot_warning(ggplot_build(p))
1515

1616
p <- ggplot(df, aes(x, y)) +
17-
stat_bin_2d(geom = "tile", origin = c(0.25, 0.5, 0.75))
17+
stat_bin_2d(geom = "tile", boundary = c(0.25, 0.5, 0.75))
1818
expect_snapshot_warning(ggplot_build(p))
1919
})
2020

0 commit comments

Comments
 (0)