From 10c420b0c11bb6c08435fd436f0fdea662610856 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 15 Jan 2024 09:32:41 +0100 Subject: [PATCH 1/4] widen range of unbounded estimation --- R/stat-density.R | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/R/stat-density.R b/R/stat-density.R index 4bf28f797b..3bef0a3406 100644 --- a/R/stat-density.R +++ b/R/stat-density.R @@ -143,10 +143,23 @@ compute_density <- function(x, w, from, to, bw = "nrd0", adjust = 1, bw <- precompute_bw(x, bw) # Decide whether to use boundary correction if (any(is.finite(bounds))) { - dens <- stats::density(x, weights = w, bw = bw, adjust = adjust, - kernel = kernel, n = n) + # To prevent discontinuities, we widen the range before calling the + # unbounded estimator (#5641). + bounds <- sort(bounds) + range <- range(from, to) + width <- diff(range) + range[1] <- range[1] - width * as.numeric(is.finite(bounds[1])) + range[2] <- range[2] + width * as.numeric(is.finite(bounds[2])) + n <- n * (sum(is.finite(bounds)) + 1) - dens <- reflect_density(dens = dens, bounds = bounds, from = from, to = to) + dens <- stats::density( + x, weights = w, bw = bw, adjust = adjust, + kernel = kernel, n = n, from = range[1], to = range[2] + ) + dens <- reflect_density( + dens = dens, bounds = bounds, + from = range[1], to = range[2] + ) } else { dens <- stats::density(x, weights = w, bw = bw, adjust = adjust, kernel = kernel, n = n, from = from, to = to) From 13fb6fd0a313a8c92bc3ffb3982951868410190a Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 15 Jan 2024 09:32:55 +0100 Subject: [PATCH 2/4] increase test tolerance --- tests/testthat/test-stat-density.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test-stat-density.R b/tests/testthat/test-stat-density.R index 677dfe5100..d1a43f7ab0 100644 --- a/tests/testthat/test-stat-density.R +++ b/tests/testthat/test-stat-density.R @@ -58,7 +58,7 @@ test_that("stat_density uses `bounds`", { expect_equal( orig_density(test_sample) + left_reflection + right_reflection, plot_density(test_sample), - tolerance = 1e-4 + tolerance = 1e-3 ) } @@ -86,7 +86,7 @@ test_that("stat_density handles data outside of `bounds`", { stat_density(bounds = c(cutoff, Inf)) ) - expect_equal(data_actual, data_expected) + expect_equal(data_actual, data_expected, tolerance = 1e-4) }) test_that("compute_density succeeds when variance is zero", { From 661ef34cf63eec1317f23f66b8fe36dc3247af09 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 15 Jan 2024 09:33:06 +0100 Subject: [PATCH 3/4] add news bullet --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 60c7877119..87a93fbf20 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,6 @@ +* The bounded density option in `stat_density()` uses a wider range to + prevent discontinuities (#5641). + # ggplot2 (development version) This is a minor release that turned out quite beefy. It is focused on From ccb3881bb97942886388bc938a61d21ce35b8daf Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 20 May 2024 11:36:19 +0200 Subject: [PATCH 4/4] move bullet --- NEWS.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 986bf3a168..50c24df127 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,7 @@ -* The bounded density option in `stat_density()` uses a wider range to - prevent discontinuities (#5641). - # ggplot2 (development version) +* The bounded density option in `stat_density()` uses a wider range to + prevent discontinuities (#5641). * `geom_raster()` now falls back to rendering as `geom_rect()` when coordinates are not Cartesian (#5503). * `stat_ecdf()` now has an optional `weight` aesthetic (@teunbrand, #5058).