Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change density default bw = "nrd0" to bw = "sj" #5854

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@

# ggplot2 (development version)

* (breaking) the default `bw` argument in `stat_density()` and `stat_ydensity()`
has changed from `"nrd0"` to `"sj"` in keeping with the recommendation given
in `?density` (@teunbrand, #3825).
* When facets coerce the faceting variables to factors, the 'ordered' class
is dropped (@teunbrand, #5666).
* `coord_map()` and `coord_polar()` throw informative warnings when used
Expand Down
16 changes: 12 additions & 4 deletions R/stat-density.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
stat_density <- function(mapping = NULL, data = NULL,
geom = "area", position = "stack",
...,
bw = "nrd0",
bw = "sj",
adjust = 1,
kernel = "gaussian",
n = 512,
Expand Down Expand Up @@ -91,7 +91,7 @@ StatDensity <- ggproto("StatDensity", Stat,

extra_params = c("na.rm", "orientation"),

compute_group = function(data, scales, bw = "nrd0", adjust = 1, kernel = "gaussian",
compute_group = function(data, scales, bw = "sj", adjust = 1, kernel = "gaussian",
n = 512, trim = FALSE, na.rm = FALSE, bounds = c(-Inf, Inf),
flipped_aes = FALSE) {
data <- flip_data(data, flipped_aes)
Expand All @@ -110,7 +110,7 @@ StatDensity <- ggproto("StatDensity", Stat,

)

compute_density <- function(x, w, from, to, bw = "nrd0", adjust = 1,
compute_density <- function(x, w, from, to, bw = "sj", adjust = 1,
kernel = "gaussian", n = 512,
bounds = c(-Inf, Inf)) {
nx <- length(x)
Expand Down Expand Up @@ -220,8 +220,16 @@ reflect_density <- function(dens, bounds, from, to) {
# Similar to stats::density.default
# Once R4.3.0 is the lowest supported version, this function can be replaced by
# using `density(..., warnWbw = FALSE)`.
precompute_bw = function(x, bw = "nrd0") {
precompute_bw = function(x, bw = "sj") {
bw <- bw[1]
if (length(x) < 2) {
cli::cli_abort("{.arg x} must contain at least 2 elements to select a \\
bandwidth automatically.")
}
if (zero_range(range(x))) {
# Many other bandwidth methods do not handle 0-variance input
return(stats::bw.nrd0(x))
}
if (is.character(bw)) {
bw <- arg_match0(bw, c("nrd0", "nrd", "ucv", "bcv", "sj", "sj-ste", "sj-dpi"))
bw <- switch(
Expand Down
29 changes: 4 additions & 25 deletions R/stat-ydensity.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
stat_ydensity <- function(mapping = NULL, data = NULL,
geom = "violin", position = "dodge",
...,
bw = "nrd0",
bw = "sj",
adjust = 1,
kernel = "gaussian",
trim = TRUE,
Expand Down Expand Up @@ -78,7 +78,7 @@ StatYdensity <- ggproto("StatYdensity", Stat,

extra_params = c("na.rm", "orientation"),

compute_group = function(self, data, scales, width = NULL, bw = "nrd0", adjust = 1,
compute_group = function(self, data, scales, width = NULL, bw = "sj", adjust = 1,
kernel = "gaussian", trim = TRUE, na.rm = FALSE,
drop = TRUE, flipped_aes = FALSE, bounds = c(-Inf, Inf)) {
if (nrow(data) < 2) {
Expand All @@ -96,7 +96,7 @@ StatYdensity <- ggproto("StatYdensity", Stat,
}
range <- range(data$y, na.rm = TRUE)
modifier <- if (trim) 0 else 3
bw <- calc_bw(data$y, bw)
bw <- precompute_bw(data$y, bw)
dens <- compute_density(
data$y, data[["weight"]],
from = range[1] - modifier * bw, to = range[2] + modifier * bw,
Expand All @@ -118,7 +118,7 @@ StatYdensity <- ggproto("StatYdensity", Stat,
dens
},

compute_panel = function(self, data, scales, width = NULL, bw = "nrd0", adjust = 1,
compute_panel = function(self, data, scales, width = NULL, bw = "sj", adjust = 1,
kernel = "gaussian", trim = TRUE, na.rm = FALSE,
scale = "area", flipped_aes = FALSE, drop = TRUE,
bounds = c(-Inf, Inf)) {
Expand Down Expand Up @@ -151,24 +151,3 @@ StatYdensity <- ggproto("StatYdensity", Stat,

dropped_aes = "weight"
)

calc_bw <- function(x, bw) {
if (is.character(bw)) {
if (length(x) < 2) {
cli::cli_abort("{.arg x} must contain at least 2 elements to select a bandwidth automatically.")
}

bw <- switch(
to_lower_ascii(bw),
nrd0 = stats::bw.nrd0(x),
nrd = stats::bw.nrd(x),
ucv = stats::bw.ucv(x),
bcv = stats::bw.bcv(x),
sj = ,
`sj-ste` = stats::bw.SJ(x, method = "ste"),
`sj-dpi` = stats::bw.SJ(x, method = "dpi"),
cli::cli_abort("{.var {bw}} is not a valid bandwidth rule.")
)
}
bw
}
2 changes: 1 addition & 1 deletion man/geom_density.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/geom_violin.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions tests/testthat/_snaps/geom-violin/basic.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions tests/testthat/_snaps/geom-violin/coord-flip.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions tests/testthat/_snaps/geom-violin/coord-polar.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions tests/testthat/_snaps/geom-violin/dodging-and-coord-flip.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions tests/testthat/_snaps/geom-violin/dodging.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions tests/testthat/_snaps/geom-violin/grouping-on-x-and-fill.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions tests/testthat/_snaps/geom-violin/narrower-width-5.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 12 additions & 12 deletions tests/testthat/_snaps/geom-violin/quantiles.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
200 changes: 99 additions & 101 deletions tests/testthat/_snaps/geom-violin/with-tails-and-points.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion tests/testthat/_snaps/stat-ydensity.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

---

`test` is not a valid bandwidth rule.
`bw` must be one of "nrd0", "nrd", "ucv", "bcv", "sj", "sj-ste", or "sj-dpi", not "test".

4 changes: 2 additions & 2 deletions tests/testthat/test-geom-violin.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ test_that("range is expanded", {
geom_violin(trim = FALSE) +
facet_grid(x ~ ., scales = "free") +
coord_cartesian(expand = FALSE)
expand_a <- stats::bw.nrd0(df$y[df$x == "a"]) * 3
expand_b <- stats::bw.nrd0(df$y[df$x == "b"]) * 3
expand_a <- stats::bw.SJ(df$y[df$x == "a"]) * 3
expand_b <- stats::bw.SJ(df$y[df$x == "b"]) * 3
expect_equal(layer_scales(p, 1)$y$dimension(), c(0 - expand_a, 1 + expand_a))
expect_equal(layer_scales(p, 2)$y$dimension(), c(0 - expand_b, 2 + expand_b))
})
Expand Down
6 changes: 3 additions & 3 deletions tests/testthat/test-stat-density.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
test_that("stat_density actually computes density", {
# Compare functon approximations because outputs from `ggplot()` and
# `density()` give grids spanning different ranges
dens <- stats::density(mtcars$mpg)
dens <- stats::density(mtcars$mpg, bw = "sj")
expected_density_fun <- stats::approxfun(data.frame(x = dens$x, y = dens$y))

plot <- ggplot(mtcars, aes(mpg)) + stat_density()
Expand All @@ -19,7 +19,7 @@ test_that("stat_density can make weighted density estimation", {
df <- mtcars
df$weight <- mtcars$cyl / sum(mtcars$cyl)

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

plot <- ggplot(df, aes(mpg, weight = weight)) + stat_density()
Expand All @@ -38,7 +38,7 @@ test_that("stat_density uses `bounds`", {
mpg_max <- max(mtcars$mpg)

expect_bounds <- function(bounds) {
dens <- stats::density(mtcars$mpg)
dens <- stats::density(mtcars$mpg, bw = "sj")
orig_density <- stats::approxfun(
data.frame(x = dens$x, y = dens$y),
yleft = 0,
Expand Down
6 changes: 3 additions & 3 deletions tests/testthat/test-stat-ydensity.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
test_that("calc_bw() requires at least two values and correct method", {
expect_snapshot_error(calc_bw(1, "nrd0"))
expect_silent(calc_bw(1:5, "nrd0"))
expect_snapshot_error(calc_bw(1:5, "test"))
expect_snapshot_error(precompute_bw(1, "nrd0"))
expect_silent(precompute_bw(1:5, "nrd0"))
expect_snapshot_error(precompute_bw(1:5, "test"))
})

test_that("`drop = FALSE` preserves groups with 1 observations", {
Expand Down