diff --git a/NEWS.md b/NEWS.md index 73c9d15683..c2df9a196a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -25,6 +25,8 @@ (@teunbrand based on @clauswilke's suggestion #5051). * Fixed a regression in `Coord$train_panel_guides()` where names of guides were dropped (@maxsutton, #5063) +* `update_geom_defaults()` and `update_stat_defaults()` now return properly + classed objects and have updated docs (@dkahle, #5146) # ggplot2 3.4.0 This is a minor release focusing on tightening up the internals and ironing out diff --git a/R/geom-defaults.r b/R/geom-defaults.r index 1fefa8c66e..afd2e598d4 100644 --- a/R/geom-defaults.r +++ b/R/geom-defaults.r @@ -7,14 +7,38 @@ #' @keywords internal #' @export #' @examples -#' update_geom_defaults("point", list(colour = "darkblue")) +#' +#' # updating a geom's default aesthetic settings +#' # example: change geom_point()'s default color +#' GeomPoint$default_aes +#' update_geom_defaults("point", aes(color = "red")) +#' GeomPoint$default_aes #' ggplot(mtcars, aes(mpg, wt)) + geom_point() -#' update_geom_defaults("point", list(colour = "black")) +#' +#' # reset default +#' update_geom_defaults("point", aes(color = "black")) +#' +#' +#' # updating a stat's default aesthetic settings +#' # example: change stat_bin()'s default y-axis to the density scale +#' StatBin$default_aes +#' update_stat_defaults("bin", aes(y = after_stat(density))) +#' StatBin$default_aes +#' ggplot(data.frame(x = rnorm(1e3)), aes(x)) + +#' geom_histogram() + +#' geom_function(fun = dnorm, color = "red") +#' +#' # reset default +#' update_stat_defaults("bin", aes(y = after_stat(count))) +#' #' @rdname update_defaults update_geom_defaults <- function(geom, new) { g <- check_subclass(geom, "Geom", env = parent.frame()) old <- g$default_aes - g$default_aes <- defaults(rename_aes(new), old) + new <- rename_aes(new) + new_names_order <- unique(c(names(old), names(new))) + new <- defaults(new, old)[new_names_order] + g$default_aes[names(new)] <- new invisible() } @@ -23,6 +47,9 @@ update_geom_defaults <- function(geom, new) { update_stat_defaults <- function(stat, new) { g <- check_subclass(stat, "Stat", env = parent.frame()) old <- g$default_aes - g$default_aes <- defaults(rename_aes(new), old) + new <- rename_aes(new) + new_names_order <- unique(c(names(old), names(new))) + new <- defaults(new, old)[new_names_order] + g$default_aes[names(new)] <- new invisible() } diff --git a/man/update_defaults.Rd b/man/update_defaults.Rd index b3cc710eb7..4c7f3a8273 100644 --- a/man/update_defaults.Rd +++ b/man/update_defaults.Rd @@ -20,8 +20,29 @@ update_stat_defaults(stat, new) Modify geom/stat aesthetic defaults for future plots } \examples{ -update_geom_defaults("point", list(colour = "darkblue")) + +# updating a geom's default aesthetic settings +# example: change geom_point()'s default color +GeomPoint$default_aes +update_geom_defaults("point", aes(color = "red")) +GeomPoint$default_aes ggplot(mtcars, aes(mpg, wt)) + geom_point() -update_geom_defaults("point", list(colour = "black")) + +# reset default +update_geom_defaults("point", aes(color = "black")) + + +# updating a stat's default aesthetic settings +# example: change stat_bin()'s default y-axis to the density scale +StatBin$default_aes +update_stat_defaults("bin", aes(y = after_stat(density))) +StatBin$default_aes +ggplot(data.frame(x = rnorm(1e3)), aes(x)) + + geom_histogram() + + geom_function(fun = dnorm, color = "red") + +# reset default +update_stat_defaults("bin", aes(y = after_stat(count))) + } \keyword{internal} diff --git a/tests/testthat/test-geom-.R b/tests/testthat/test-geom-.R index 9436770838..409aa19b8f 100644 --- a/tests/testthat/test-geom-.R +++ b/tests/testthat/test-geom-.R @@ -5,3 +5,47 @@ test_that("aesthetic checking in geom throws correct errors", { aes <- list(a = 1:4, b = letters[1:4], c = TRUE, d = 1:2, e = 1:5) expect_snapshot_error(check_aesthetics(aes, 4)) }) + + + +test_that("updating geom aesthetic defaults preserves class and order", { + + original_defaults <- GeomPoint$default_aes + + update_geom_defaults("point", aes(color = "red")) + + updated_defaults <- GeomPoint$default_aes + + expect_s3_class(updated_defaults, "uneval") + + intended_defaults <- original_defaults + intended_defaults[["colour"]] <- "red" + + expect_equal(updated_defaults, intended_defaults) + + update_geom_defaults("point", original_defaults) + +}) + + + + +test_that("updating stat aesthetic defaults preserves class and order", { + + original_defaults <- StatBin$default_aes + + update_stat_defaults("bin", aes(y = after_stat(density))) + + updated_defaults <- StatBin$default_aes + + expect_s3_class(updated_defaults, "uneval") + + intended_defaults <- original_defaults + intended_defaults[["y"]] <- expr(after_stat(density)) + attr(intended_defaults[["y"]], ".Environment") <- attr(updated_defaults[["y"]], ".Environment") + + expect_equal(updated_defaults, intended_defaults) + + update_stat_defaults("bin", original_defaults) + +})