Skip to content

Commit 4ef0284

Browse files
authored
Silence new density() warning (#5281)
* precompute bandwidth * Better code comment * Add namespaces to bandwidth functions
1 parent b9f43f2 commit 4ef0284

File tree

5 files changed

+49
-4
lines changed

5 files changed

+49
-4
lines changed

R/stat-density.R

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#' @param bw The smoothing bandwidth to be used.
22
#' If numeric, the standard deviation of the smoothing kernel.
33
#' If character, a rule to choose the bandwidth, as listed in
4-
#' [stats::bw.nrd()].
4+
#' [stats::bw.nrd()]. Note that automatic calculation of the bandwidth does
5+
#' not take weights into account.
56
#' @param adjust A multiplicate bandwidth adjustment. This makes it possible
67
#' to adjust the bandwidth while still using the a bandwidth estimator.
78
#' For example, `adjust = 1/2` means use half of the default bandwidth.
@@ -139,6 +140,7 @@ compute_density <- function(x, w, from, to, bw = "nrd0", adjust = 1,
139140
))
140141
}
141142

143+
bw <- precompute_bw(x, bw)
142144
# Decide whether to use boundary correction
143145
if (any(is.finite(bounds))) {
144146
dens <- stats::density(x, weights = w, bw = bw, adjust = adjust,
@@ -214,3 +216,29 @@ reflect_density <- function(dens, bounds, from, to) {
214216

215217
list(x = out_x, y = out_y)
216218
}
219+
220+
# Similar to stats::density.default
221+
# Once R4.3.0 is the lowest supported version, this function can be replaced by
222+
# using `density(..., warnWbw = FALSE)`.
223+
precompute_bw = function(x, bw = "nrd0") {
224+
bw <- bw[1]
225+
if (is.character(bw)) {
226+
bw <- arg_match0(bw, c("nrd0", "nrd", "ucv", "bcv", "sj", "sj-ste", "sj-dpi"))
227+
bw <- switch(
228+
to_lower_ascii(bw),
229+
nrd0 = stats::bw.nrd0(x),
230+
nrd = stats::bw.nrd(x),
231+
ucv = stats::bw.ucv(x),
232+
bcv = stats::bw.bcv(x),
233+
sj = ,
234+
`sj-ste` = stats::bw.SJ(x, method = "ste"),
235+
`sj-dpi` = stats::bw.SJ(x, method = "dpi")
236+
)
237+
}
238+
if (!is.numeric(bw) || bw <= 0 || !is.finite(bw)) {
239+
cli::cli_abort(
240+
"{.arg bw} must be a finite, positive number, not {obj_type_friendly(bw)}."
241+
)
242+
}
243+
bw
244+
}

man/geom_density.Rd

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/geom_violin.Rd

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/_snaps/stat-density.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,11 @@
55
Caused by error in `setup_params()`:
66
! `stat_density()` requires an x or y aesthetic.
77

8+
# precompute_bandwidth() errors appropriately
9+
10+
`bw` must be one of "nrd0", "nrd", "ucv", "bcv", "sj", "sj-ste", or "sj-dpi", not "foobar".
11+
12+
---
13+
14+
`bw` must be a finite, positive number, not `Inf`.
15+

tests/testthat/test-stat-density.R

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test_that("stat_density can make weighted density estimation", {
1919
df <- mtcars
2020
df$weight <- mtcars$cyl / sum(mtcars$cyl)
2121

22-
dens <- stats::density(df$mpg, weights = df$weight)
22+
dens <- stats::density(df$mpg, weights = df$weight, bw = bw.nrd0(df$mpg))
2323
expected_density_fun <- stats::approxfun(data.frame(x = dens$x, y = dens$y))
2424

2525
plot <- ggplot(df, aes(mpg, weight = weight)) + stat_density()
@@ -118,3 +118,10 @@ test_that("compute_density returns useful df and throws warning when <2 values",
118118
expect_equal(names(dens), c("x", "density", "scaled", "ndensity", "count", "n"))
119119
expect_type(dens$x, "double")
120120
})
121+
122+
test_that("precompute_bandwidth() errors appropriately", {
123+
expect_silent(precompute_bw(1:10))
124+
expect_equal(precompute_bw(1:10, 5), 5)
125+
expect_snapshot_error(precompute_bw(1:10, bw = "foobar"))
126+
expect_snapshot_error(precompute_bw(1:10, bw = Inf))
127+
})

0 commit comments

Comments
 (0)