From 57c2a71fb23c6ea3138a40553e1fcd5c75b4a3ec Mon Sep 17 00:00:00 2001 From: David Kahle Date: Wed, 11 Jan 2023 09:17:44 -0600 Subject: [PATCH 1/8] Closes #5145 --- R/geom-defaults.r | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/geom-defaults.r b/R/geom-defaults.r index 1fefa8c66e..71c37a8c43 100644 --- a/R/geom-defaults.r +++ b/R/geom-defaults.r @@ -15,6 +15,7 @@ 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) + class(g$default_aes) <- "uneval" invisible() } @@ -24,5 +25,6 @@ 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) + class(g$default_aes) <- "uneval" invisible() } From 4abac61c1cf2109f3f23134cbcd08667d4c2376a Mon Sep 17 00:00:00 2001 From: David Kahle Date: Thu, 12 Jan 2023 08:38:38 -0600 Subject: [PATCH 2/8] uppdate_(geom|stat)_defaults: don't manually class, add GeomPoint$default_aes to docs --- R/geom-defaults.r | 10 +++++----- man/update_defaults.Rd | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/R/geom-defaults.r b/R/geom-defaults.r index 71c37a8c43..09d30c9b08 100644 --- a/R/geom-defaults.r +++ b/R/geom-defaults.r @@ -7,15 +7,16 @@ #' @keywords internal #' @export #' @examples -#' update_geom_defaults("point", list(colour = "darkblue")) +#' GeomPoint$default_aes +#' update_geom_defaults("point", list(color = "red")) +#' GeomPoint$default_aes #' ggplot(mtcars, aes(mpg, wt)) + geom_point() #' update_geom_defaults("point", list(colour = "black")) #' @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) - class(g$default_aes) <- "uneval" + g$default_aes[] <- defaults(rename_aes(new), old)[names(g$default_aes)] invisible() } @@ -24,7 +25,6 @@ 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) - class(g$default_aes) <- "uneval" + g$default_aes[] <- defaults(rename_aes(new), old)[names(g$default_aes)] invisible() } diff --git a/man/update_defaults.Rd b/man/update_defaults.Rd index b3cc710eb7..f58c775b46 100644 --- a/man/update_defaults.Rd +++ b/man/update_defaults.Rd @@ -20,7 +20,9 @@ update_stat_defaults(stat, new) Modify geom/stat aesthetic defaults for future plots } \examples{ -update_geom_defaults("point", list(colour = "darkblue")) +GeomPoint$default_aes +update_geom_defaults("point", list(color = "red")) +GeomPoint$default_aes ggplot(mtcars, aes(mpg, wt)) + geom_point() update_geom_defaults("point", list(colour = "black")) } From 607089c9ceb21c21ce5d28f72cad1e07a2eca033 Mon Sep 17 00:00:00 2001 From: David Kahle Date: Thu, 12 Jan 2023 08:41:14 -0600 Subject: [PATCH 3/8] geom defaults: simplify name reorder logic --- R/geom-defaults.r | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/geom-defaults.r b/R/geom-defaults.r index 09d30c9b08..fc854e36e8 100644 --- a/R/geom-defaults.r +++ b/R/geom-defaults.r @@ -16,7 +16,7 @@ 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)[names(g$default_aes)] + g$default_aes[] <- defaults(rename_aes(new), old)[names(old)] invisible() } @@ -25,6 +25,6 @@ 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)[names(g$default_aes)] + g$default_aes[] <- defaults(rename_aes(new), old)[names(old)] invisible() } From d526484866cf7ab8a36c89573edea30c34770e96 Mon Sep 17 00:00:00 2001 From: David Kahle Date: Tue, 24 Jan 2023 11:20:37 -0600 Subject: [PATCH 4/8] allow better stat defaults updating with examples, add tests --- R/geom-defaults.r | 33 ++++++++++++++++++++++++++-- man/update_defaults.Rd | 23 ++++++++++++++++++++ tests/testthat/test-geom-.R | 43 +++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) diff --git a/R/geom-defaults.r b/R/geom-defaults.r index fc854e36e8..5c42d4b10e 100644 --- a/R/geom-defaults.r +++ b/R/geom-defaults.r @@ -7,16 +7,42 @@ #' @keywords internal #' @export #' @examples +#' +#' # updating a geom's default aesthetic settings +#' # example: change geom_point()'s default color #' GeomPoint$default_aes #' update_geom_defaults("point", list(color = "red")) #' GeomPoint$default_aes #' ggplot(mtcars, aes(mpg, wt)) + geom_point() +#' +#' # reset default #' update_geom_defaults("point", list(colour = "black")) +#' +#' # note: adding default aesthetics is possible +#' # update_geom_defaults("point", list(foo = "bar")) +#' # GeomPoint$default_aes +#' +#' +#' # 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", list(y = expr(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", list(y = expr(after_stat(density)))) +#' #' @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)[names(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() } @@ -25,6 +51,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)[names(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 f58c775b46..dea2b0a6ca 100644 --- a/man/update_defaults.Rd +++ b/man/update_defaults.Rd @@ -20,10 +20,33 @@ update_stat_defaults(stat, new) Modify geom/stat aesthetic defaults for future plots } \examples{ + +# updating a geom's default aesthetic settings +# example: change geom_point()'s default color GeomPoint$default_aes update_geom_defaults("point", list(color = "red")) GeomPoint$default_aes ggplot(mtcars, aes(mpg, wt)) + geom_point() + +# reset default update_geom_defaults("point", list(colour = "black")) + +# note: adding default aesthetics is possible +# update_geom_defaults("point", list(foo = "bar")) +# GeomPoint$default_aes + + +# 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", list(y = expr(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", list(y = expr(after_stat(density)))) + } \keyword{internal} diff --git a/tests/testthat/test-geom-.R b/tests/testthat/test-geom-.R index 9436770838..b3a28f5a93 100644 --- a/tests/testthat/test-geom-.R +++ b/tests/testthat/test-geom-.R @@ -5,3 +5,46 @@ 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", list(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", list(y = expr(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)) + + expect_equal(updated_defaults, intended_defaults) + + update_stat_defaults("bin", original_defaults) + +}) From a73d21adb1c76c80d57b0a7b857515a59c3479a0 Mon Sep 17 00:00:00 2001 From: David Kahle Date: Tue, 24 Jan 2023 14:43:42 -0600 Subject: [PATCH 5/8] update_geom_defaults() added to news.md --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) 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 From 86c4076b4bd4bffb63a3016c76acfbe451ab2881 Mon Sep 17 00:00:00 2001 From: David Kahle Date: Tue, 24 Jan 2023 14:45:26 -0600 Subject: [PATCH 6/8] remove non-used aesthetics from update_geom_defaults() docs --- R/geom-defaults.r | 4 ---- man/update_defaults.Rd | 4 ---- 2 files changed, 8 deletions(-) diff --git a/R/geom-defaults.r b/R/geom-defaults.r index 5c42d4b10e..7483a917cc 100644 --- a/R/geom-defaults.r +++ b/R/geom-defaults.r @@ -18,10 +18,6 @@ #' # reset default #' update_geom_defaults("point", list(colour = "black")) #' -#' # note: adding default aesthetics is possible -#' # update_geom_defaults("point", list(foo = "bar")) -#' # GeomPoint$default_aes -#' #' #' # updating a stat's default aesthetic settings #' # example: change stat_bin()'s default y-axis to the density scale diff --git a/man/update_defaults.Rd b/man/update_defaults.Rd index dea2b0a6ca..420fa8c7a2 100644 --- a/man/update_defaults.Rd +++ b/man/update_defaults.Rd @@ -31,10 +31,6 @@ ggplot(mtcars, aes(mpg, wt)) + geom_point() # reset default update_geom_defaults("point", list(colour = "black")) -# note: adding default aesthetics is possible -# update_geom_defaults("point", list(foo = "bar")) -# GeomPoint$default_aes - # updating a stat's default aesthetic settings # example: change stat_bin()'s default y-axis to the density scale From 79ff57a5bcd169fe9b9001431053f580c1f6fb20 Mon Sep 17 00:00:00 2001 From: David Kahle Date: Tue, 24 Jan 2023 15:43:46 -0600 Subject: [PATCH 7/8] update_(geom|stat)_defaults(): use aes() instead of list() --- R/geom-defaults.r | 8 ++++---- man/update_defaults.Rd | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/R/geom-defaults.r b/R/geom-defaults.r index 7483a917cc..afd2e598d4 100644 --- a/R/geom-defaults.r +++ b/R/geom-defaults.r @@ -11,25 +11,25 @@ #' # updating a geom's default aesthetic settings #' # example: change geom_point()'s default color #' GeomPoint$default_aes -#' update_geom_defaults("point", list(color = "red")) +#' update_geom_defaults("point", aes(color = "red")) #' GeomPoint$default_aes #' ggplot(mtcars, aes(mpg, wt)) + geom_point() #' #' # reset default -#' update_geom_defaults("point", list(colour = "black")) +#' 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", list(y = expr(after_stat(density)))) +#' 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", list(y = expr(after_stat(density)))) +#' update_stat_defaults("bin", aes(y = after_stat(count))) #' #' @rdname update_defaults update_geom_defaults <- function(geom, new) { diff --git a/man/update_defaults.Rd b/man/update_defaults.Rd index 420fa8c7a2..4c7f3a8273 100644 --- a/man/update_defaults.Rd +++ b/man/update_defaults.Rd @@ -24,25 +24,25 @@ Modify geom/stat aesthetic defaults for future plots # updating a geom's default aesthetic settings # example: change geom_point()'s default color GeomPoint$default_aes -update_geom_defaults("point", list(color = "red")) +update_geom_defaults("point", aes(color = "red")) GeomPoint$default_aes ggplot(mtcars, aes(mpg, wt)) + geom_point() # reset default -update_geom_defaults("point", list(colour = "black")) +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", list(y = expr(after_stat(density)))) +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", list(y = expr(after_stat(density)))) +update_stat_defaults("bin", aes(y = after_stat(count))) } \keyword{internal} From ddd03bfbf37cfc7a4e3b15bb724be01120d3b09c Mon Sep 17 00:00:00 2001 From: David Kahle Date: Wed, 25 Jan 2023 01:54:51 -0600 Subject: [PATCH 8/8] use aes() construction in tests --- tests/testthat/test-geom-.R | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test-geom-.R b/tests/testthat/test-geom-.R index b3a28f5a93..409aa19b8f 100644 --- a/tests/testthat/test-geom-.R +++ b/tests/testthat/test-geom-.R @@ -12,7 +12,7 @@ test_that("updating geom aesthetic defaults preserves class and order", { original_defaults <- GeomPoint$default_aes - update_geom_defaults("point", list(color = "red")) + update_geom_defaults("point", aes(color = "red")) updated_defaults <- GeomPoint$default_aes @@ -34,7 +34,7 @@ test_that("updating stat aesthetic defaults preserves class and order", { original_defaults <- StatBin$default_aes - update_stat_defaults("bin", list(y = expr(after_stat(density)))) + update_stat_defaults("bin", aes(y = after_stat(density))) updated_defaults <- StatBin$default_aes @@ -42,6 +42,7 @@ test_that("updating stat aesthetic defaults preserves class and order", { 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)