Skip to content

Commit e22cff2

Browse files
authored
Avoid bounded density discontinuity (#5642)
* widen range of unbounded estimation * increase test tolerance * add news bullet * move bullet
1 parent b3d5071 commit e22cff2

File tree

3 files changed

+20
-5
lines changed

3 files changed

+20
-5
lines changed

NEWS.md

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

3+
* The bounded density option in `stat_density()` uses a wider range to
4+
prevent discontinuities (#5641).
35
* `geom_raster()` now falls back to rendering as `geom_rect()` when coordinates
46
are not Cartesian (#5503).
57
* `stat_ecdf()` now has an optional `weight` aesthetic (@teunbrand, #5058).

R/stat-density.R

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,23 @@ compute_density <- function(x, w, from, to, bw = "nrd0", adjust = 1,
148148
bw <- precompute_bw(x, bw)
149149
# Decide whether to use boundary correction
150150
if (any(is.finite(bounds))) {
151-
dens <- stats::density(x, weights = w, bw = bw, adjust = adjust,
152-
kernel = kernel, n = n)
151+
# To prevent discontinuities, we widen the range before calling the
152+
# unbounded estimator (#5641).
153+
bounds <- sort(bounds)
154+
range <- range(from, to)
155+
width <- diff(range)
156+
range[1] <- range[1] - width * as.numeric(is.finite(bounds[1]))
157+
range[2] <- range[2] + width * as.numeric(is.finite(bounds[2]))
158+
n <- n * (sum(is.finite(bounds)) + 1)
153159

154-
dens <- reflect_density(dens = dens, bounds = bounds, from = from, to = to)
160+
dens <- stats::density(
161+
x, weights = w, bw = bw, adjust = adjust,
162+
kernel = kernel, n = n, from = range[1], to = range[2]
163+
)
164+
dens <- reflect_density(
165+
dens = dens, bounds = bounds,
166+
from = range[1], to = range[2]
167+
)
155168
} else {
156169
dens <- stats::density(x, weights = w, bw = bw, adjust = adjust,
157170
kernel = kernel, n = n, from = from, to = to)

tests/testthat/test-stat-density.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ test_that("stat_density uses `bounds`", {
6666
expect_equal(
6767
orig_density(test_sample) + left_reflection + right_reflection,
6868
plot_density(test_sample),
69-
tolerance = 1e-4
69+
tolerance = 1e-3
7070
)
7171
}
7272

@@ -94,7 +94,7 @@ test_that("stat_density handles data outside of `bounds`", {
9494
stat_density(bounds = c(cutoff, Inf))
9595
)
9696

97-
expect_equal(data_actual, data_expected)
97+
expect_equal(data_actual, data_expected, tolerance = 1e-4)
9898
})
9999

100100
test_that("compute_density succeeds when variance is zero", {

0 commit comments

Comments
 (0)