From 35f8eb0ae9779ef5a3b6b39b40cfac487adfee2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 13 Jan 2017 15:33:20 +0100 Subject: [PATCH 01/17] position_jitter() gains seed argument --- R/position-jitter.r | 15 ++++++++++----- R/utilities.r | 10 ++++++++++ man/position_jitter.Rd | 4 +++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/R/position-jitter.r b/R/position-jitter.r index 8f65e7eca1..85dca8dc9e 100644 --- a/R/position-jitter.r +++ b/R/position-jitter.r @@ -13,6 +13,9 @@ #' jitter values will occupy 80\% of the implied bins. Categorical data #' is aligned on the integers, so a width or height of 0.5 will spread the #' data so it's not possible to see the distinction between the categories. +#' @param seed An optional random seed to make the jitter reproducible. +#' Useful if you need to apply the same jitter twice, e.g., for a point and +#' a corresponding label. #' @export #' @examples #' # Jittering is useful when you have a discrete position, and a relatively @@ -31,10 +34,11 @@ #' geom_jitter(width = 0.1, height = 0.1) #' ggplot(mtcars, aes(am, vs)) + #' geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) -position_jitter <- function(width = NULL, height = NULL) { +position_jitter <- function(width = NULL, height = NULL, seed = NULL) { ggproto(NULL, PositionJitter, width = width, - height = height + height = height, + seed = seed ) } @@ -48,13 +52,14 @@ PositionJitter <- ggproto("PositionJitter", Position, setup_params = function(self, data) { list( width = self$width %||% (resolution(data$x, zero = FALSE) * 0.4), - height = self$height %||% (resolution(data$y, zero = FALSE) * 0.4) + height = self$height %||% (resolution(data$y, zero = FALSE) * 0.4), + seed = self$seed ) }, compute_layer = function(data, params, panel) { - trans_x <- if (params$width > 0) function(x) jitter(x, amount = params$width) - trans_y <- if (params$height > 0) function(x) jitter(x, amount = params$height) + trans_x <- if (params$width > 0) function(x) with_seed(params$seed, jitter(x, amount = params$width)) + trans_y <- if (params$height > 0) function(x) with_seed(params$seed, jitter(x, amount = params$height)) transform_position(data, trans_x, trans_y) } diff --git a/R/utilities.r b/R/utilities.r index 0d93691676..18a3bba571 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -299,6 +299,16 @@ find_args <- function(...) { # global data dummy_data <- function() data.frame(x = NA) +with_seed <- function(seed, code) { + if (!is.null(seed)) { + old_seed <- get0(".Random.seed", globalenv()) + if (!is.null(old_seed)) { + on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) + } + } + code +} + # Needed to trigger package loading #' @importFrom tibble tibble NULL diff --git a/man/position_jitter.Rd b/man/position_jitter.Rd index df8e8880a1..a0460e819b 100644 --- a/man/position_jitter.Rd +++ b/man/position_jitter.Rd @@ -4,7 +4,7 @@ \alias{position_jitter} \title{Jitter points to avoid overplotting} \usage{ -position_jitter(width = NULL, height = NULL) +position_jitter(width = NULL, height = NULL, seed = NULL) } \arguments{ \item{width, height}{Amount of vertical and horizontal jitter. The jitter @@ -15,6 +15,8 @@ position_jitter(width = NULL, height = NULL) jitter values will occupy 80\% of the implied bins. Categorical data is aligned on the integers, so a width or height of 0.5 will spread the data so it's not possible to see the distinction between the categories.} + +\item{seed}{An optional random seed to make the jitter reproducible.} } \description{ Couterintuitively adding random noise to a plot can sometimes make it From 9c9951e8ad0185f1de61583866803bf755861b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 25 Jan 2017 09:50:40 +0100 Subject: [PATCH 02/17] use only one with_seed() call --- R/position-jitter.r | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/R/position-jitter.r b/R/position-jitter.r index 85dca8dc9e..d2443ab760 100644 --- a/R/position-jitter.r +++ b/R/position-jitter.r @@ -58,9 +58,9 @@ PositionJitter <- ggproto("PositionJitter", Position, }, compute_layer = function(data, params, panel) { - trans_x <- if (params$width > 0) function(x) with_seed(params$seed, jitter(x, amount = params$width)) - trans_y <- if (params$height > 0) function(x) with_seed(params$seed, jitter(x, amount = params$height)) + trans_x <- if (params$width > 0) function(x) jitter(x, amount = params$width) + trans_y <- if (params$height > 0) function(x) jitter(x, amount = params$height) - transform_position(data, trans_x, trans_y) + with_seed(params$seed, transform_position(data, trans_x, trans_y)) } ) From b789ed395e347b253e5edc3ae6fa802d89a9d6fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 25 Jan 2017 15:55:07 +0100 Subject: [PATCH 03/17] use mode = 'integer' --- R/utilities.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utilities.r b/R/utilities.r index 18a3bba571..bb8bd3f3af 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -301,7 +301,7 @@ dummy_data <- function() data.frame(x = NA) with_seed <- function(seed, code) { if (!is.null(seed)) { - old_seed <- get0(".Random.seed", globalenv()) + old_seed <- get0(".Random.seed", globalenv(), mode = "integer") if (!is.null(old_seed)) { on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) } From 5bfcb597bfb8d624336b735118c864d5300c1236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Wed, 25 Jan 2017 15:58:42 +0100 Subject: [PATCH 04/17] actually set seed --- R/utilities.r | 1 + 1 file changed, 1 insertion(+) diff --git a/R/utilities.r b/R/utilities.r index bb8bd3f3af..06382f3e9c 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -305,6 +305,7 @@ with_seed <- function(seed, code) { if (!is.null(old_seed)) { on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) } + set.seed(seed) } code } From f227475c67ba05588aebae3dfbaa30f8d33140c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 3 Feb 2017 00:01:11 +0100 Subject: [PATCH 05/17] fixed seed by default --- R/position-jitter.r | 6 ++++-- man/position_jitter.Rd | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/R/position-jitter.r b/R/position-jitter.r index d2443ab760..d421af7ba4 100644 --- a/R/position-jitter.r +++ b/R/position-jitter.r @@ -13,9 +13,11 @@ #' jitter values will occupy 80\% of the implied bins. Categorical data #' is aligned on the integers, so a width or height of 0.5 will spread the #' data so it's not possible to see the distinction between the categories. -#' @param seed An optional random seed to make the jitter reproducible. +#' @param seed A random seed to make the jitter reproducible. #' Useful if you need to apply the same jitter twice, e.g., for a point and #' a corresponding label. +#' The random seed is reset after jittering, +#' use `NULL` to use the current random seed and avoid resetting. #' @export #' @examples #' # Jittering is useful when you have a discrete position, and a relatively @@ -34,7 +36,7 @@ #' geom_jitter(width = 0.1, height = 0.1) #' ggplot(mtcars, aes(am, vs)) + #' geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) -position_jitter <- function(width = NULL, height = NULL, seed = NULL) { +position_jitter <- function(width = NULL, height = NULL, seed = 4L) { ggproto(NULL, PositionJitter, width = width, height = height, diff --git a/man/position_jitter.Rd b/man/position_jitter.Rd index a0460e819b..6d36c339a1 100644 --- a/man/position_jitter.Rd +++ b/man/position_jitter.Rd @@ -4,7 +4,7 @@ \alias{position_jitter} \title{Jitter points to avoid overplotting} \usage{ -position_jitter(width = NULL, height = NULL, seed = NULL) +position_jitter(width = NULL, height = NULL, seed = 4L) } \arguments{ \item{width, height}{Amount of vertical and horizontal jitter. The jitter @@ -16,7 +16,11 @@ position_jitter(width = NULL, height = NULL, seed = NULL) is aligned on the integers, so a width or height of 0.5 will spread the data so it's not possible to see the distinction between the categories.} -\item{seed}{An optional random seed to make the jitter reproducible.} +\item{seed}{A random seed to make the jitter reproducible. +Useful if you need to apply the same jitter twice, e.g., for a point and +a corresponding label. +The random seed is reset after jittering, +use `NULL` to use the current random seed and avoid resetting.} } \description{ Couterintuitively adding random noise to a plot can sometimes make it From d6122768de7342db8d7ec86a1c6a03beaf9df9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 3 Feb 2017 00:02:09 +0100 Subject: [PATCH 06/17] NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 12746fc39f..54284565c7 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ +* `position_jitter()` gains a `seed` argument that allows specifying a random + seed for reproducible jittering (#1996, @krlmlr). + ggplot2 1.0.1 ---------------------------------------------------------------- From b988c0ab7e00d7ecee2c4639b957e616c2a6caeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 4 Feb 2017 18:29:36 +0100 Subject: [PATCH 07/17] support seed = NA, which is now the default in this mode, the random seed is not changed, but reset after processing --- R/position-jitter.r | 8 +++++--- R/utilities.r | 4 +++- man/position_jitter.Rd | 8 +++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/R/position-jitter.r b/R/position-jitter.r index d421af7ba4..7f7a2fcc20 100644 --- a/R/position-jitter.r +++ b/R/position-jitter.r @@ -16,8 +16,10 @@ #' @param seed A random seed to make the jitter reproducible. #' Useful if you need to apply the same jitter twice, e.g., for a point and #' a corresponding label. -#' The random seed is reset after jittering, -#' use `NULL` to use the current random seed and avoid resetting. +#' The random seed is reset after jittering. +#' If `NA` (the default value), the current random seed is used. +#' Use `NULL` to use the current random seed and also avoid resetting +#' (the behavior of \pkg{ggplot} 2.2.1 and earlier). #' @export #' @examples #' # Jittering is useful when you have a discrete position, and a relatively @@ -36,7 +38,7 @@ #' geom_jitter(width = 0.1, height = 0.1) #' ggplot(mtcars, aes(am, vs)) + #' geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) -position_jitter <- function(width = NULL, height = NULL, seed = 4L) { +position_jitter <- function(width = NULL, height = NULL, seed = NA) { ggproto(NULL, PositionJitter, width = width, height = height, diff --git a/R/utilities.r b/R/utilities.r index 06382f3e9c..93ad7a222c 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -305,7 +305,9 @@ with_seed <- function(seed, code) { if (!is.null(old_seed)) { on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) } - set.seed(seed) + if (!is.na(seed)) { + set.seed(seed) + } } code } diff --git a/man/position_jitter.Rd b/man/position_jitter.Rd index 6d36c339a1..4a377b598a 100644 --- a/man/position_jitter.Rd +++ b/man/position_jitter.Rd @@ -4,7 +4,7 @@ \alias{position_jitter} \title{Jitter points to avoid overplotting} \usage{ -position_jitter(width = NULL, height = NULL, seed = 4L) +position_jitter(width = NULL, height = NULL, seed = NA) } \arguments{ \item{width, height}{Amount of vertical and horizontal jitter. The jitter @@ -19,8 +19,10 @@ position_jitter(width = NULL, height = NULL, seed = 4L) \item{seed}{A random seed to make the jitter reproducible. Useful if you need to apply the same jitter twice, e.g., for a point and a corresponding label. -The random seed is reset after jittering, -use `NULL` to use the current random seed and avoid resetting.} +The random seed is reset after jittering. +If `NA` (the default value), the current random seed is used. +Use `NULL` to use the current random seed and also avoid resetting +(the behavior of \pkg{ggplot} 2.2.1 and earlier).} } \description{ Couterintuitively adding random noise to a plot can sometimes make it From 6f20e6ccfe5b06ea44037d252957c88532084c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 4 Feb 2017 18:36:43 +0100 Subject: [PATCH 08/17] with_seed() always initializes RNG --- R/utilities.r | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/R/utilities.r b/R/utilities.r index 93ad7a222c..40e0f3421b 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -301,10 +301,13 @@ dummy_data <- function() data.frame(x = NA) with_seed <- function(seed, code) { if (!is.null(seed)) { - old_seed <- get0(".Random.seed", globalenv(), mode = "integer") - if (!is.null(old_seed)) { - on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) + old_seed <- get_seed() + if (is.null(old_seed)) { + # Trigger initialisation of RNG + runif(1L) + old_seed <- get_seed() } + on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) if (!is.na(seed)) { set.seed(seed) } @@ -312,6 +315,10 @@ with_seed <- function(seed, code) { code } +get_seed <- function() { + get0(".Random.seed", globalenv(), mode = "integer") +} + # Needed to trigger package loading #' @importFrom tibble tibble NULL From a00407e6640a4bf2a7c6223b8fa8e7b97d578f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sat, 4 Feb 2017 20:33:50 +0100 Subject: [PATCH 09/17] added example --- R/position-jitter.r | 6 ++++++ man/position_jitter.Rd | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/R/position-jitter.r b/R/position-jitter.r index 7f7a2fcc20..6f647e4f67 100644 --- a/R/position-jitter.r +++ b/R/position-jitter.r @@ -38,6 +38,12 @@ #' geom_jitter(width = 0.1, height = 0.1) #' ggplot(mtcars, aes(am, vs)) + #' geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) +#' +#' # Reproducible jitter by default +#' ggplot(mtcars, aes(am, vs)) + +#' geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) +#' geom_jitter(position = position_jitter(width = 0.1, height = 0.1), +#' color = red, aes(am + 0.2, vs + 0.2)) position_jitter <- function(width = NULL, height = NULL, seed = NA) { ggproto(NULL, PositionJitter, width = width, diff --git a/man/position_jitter.Rd b/man/position_jitter.Rd index 4a377b598a..1afb0ad35e 100644 --- a/man/position_jitter.Rd +++ b/man/position_jitter.Rd @@ -46,6 +46,12 @@ ggplot(mtcars, aes(am, vs)) + geom_jitter(width = 0.1, height = 0.1) ggplot(mtcars, aes(am, vs)) + geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) + +# Reproducible jitter by default +ggplot(mtcars, aes(am, vs)) + + geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) + geom_jitter(position = position_jitter(width = 0.1, height = 0.1), + color = red, aes(am + 0.2, vs + 0.2)) } \seealso{ Other position adjustments: \code{\link{position_dodge}}, From f0d3e1a1afa42a3c12b628a6e409ed4ea2ad040a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 7 Feb 2017 12:37:39 +0100 Subject: [PATCH 10/17] extract function --- R/utilities.r | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/R/utilities.r b/R/utilities.r index 40e0f3421b..b1d40e36b2 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -301,12 +301,7 @@ dummy_data <- function() data.frame(x = NA) with_seed <- function(seed, code) { if (!is.null(seed)) { - old_seed <- get_seed() - if (is.null(old_seed)) { - # Trigger initialisation of RNG - runif(1L) - old_seed <- get_seed() - } + old_seed <- get_valid_seed() on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) if (!is.na(seed)) { set.seed(seed) @@ -315,6 +310,16 @@ with_seed <- function(seed, code) { code } +get_valid_seed <- function() { + seed <- get_seed() + if (is.null(seed)) { + # Trigger initialisation of RNG + runif(1L) + seed <- get_seed() + } + seed +} + get_seed <- function() { get0(".Random.seed", globalenv(), mode = "integer") } From ae4f33c8eb22e781f210f4321cd53ee3a380c707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 7 Feb 2017 12:37:51 +0100 Subject: [PATCH 11/17] fix and clarify example --- R/position-jitter.r | 8 ++++---- man/position_jitter.Rd | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/R/position-jitter.r b/R/position-jitter.r index 6f647e4f67..b4c079a409 100644 --- a/R/position-jitter.r +++ b/R/position-jitter.r @@ -39,11 +39,11 @@ #' ggplot(mtcars, aes(am, vs)) + #' geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) #' -#' # Reproducible jitter by default +#' # Create a jitter object for reproducible jitter: +#' jitter <- position_jitter(width = 0.1, height = 0.1) #' ggplot(mtcars, aes(am, vs)) + -#' geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) -#' geom_jitter(position = position_jitter(width = 0.1, height = 0.1), -#' color = red, aes(am + 0.2, vs + 0.2)) +#' geom_point(position = jitter) + +#' geom_point(position = jitter, color = "red", aes(am + 0.2, vs + 0.2)) position_jitter <- function(width = NULL, height = NULL, seed = NA) { ggproto(NULL, PositionJitter, width = width, diff --git a/man/position_jitter.Rd b/man/position_jitter.Rd index 1afb0ad35e..d7435f14cd 100644 --- a/man/position_jitter.Rd +++ b/man/position_jitter.Rd @@ -47,11 +47,11 @@ ggplot(mtcars, aes(am, vs)) + ggplot(mtcars, aes(am, vs)) + geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) -# Reproducible jitter by default +# Create a jitter object for reproducible jitter: +jitter <- position_jitter(width = 0.1, height = 0.1) ggplot(mtcars, aes(am, vs)) + - geom_jitter(position = position_jitter(width = 0.1, height = 0.1)) - geom_jitter(position = position_jitter(width = 0.1, height = 0.1), - color = red, aes(am + 0.2, vs + 0.2)) + geom_point(position = jitter) + + geom_point(position = jitter, color = "red", aes(am + 0.2, vs + 0.2)) } \seealso{ Other position adjustments: \code{\link{position_dodge}}, From 28b114b68b638f33b1c6d3297dbac664cf4649b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 7 Feb 2017 12:43:41 +0100 Subject: [PATCH 12/17] NA picks a random seed using sample.int() --- R/position-jitter.r | 3 ++- R/utilities.r | 5 +++-- man/position_jitter.Rd | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/R/position-jitter.r b/R/position-jitter.r index b4c079a409..6b8350b299 100644 --- a/R/position-jitter.r +++ b/R/position-jitter.r @@ -17,7 +17,8 @@ #' Useful if you need to apply the same jitter twice, e.g., for a point and #' a corresponding label. #' The random seed is reset after jittering. -#' If `NA` (the default value), the current random seed is used. +#' If `NA` (the default value), the seed is initialised with a random value; +#' this makes sure that two subsequent calls start with a different seed. #' Use `NULL` to use the current random seed and also avoid resetting #' (the behavior of \pkg{ggplot} 2.2.1 and earlier). #' @export diff --git a/R/utilities.r b/R/utilities.r index b1d40e36b2..5cb065de79 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -303,9 +303,10 @@ with_seed <- function(seed, code) { if (!is.null(seed)) { old_seed <- get_valid_seed() on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) - if (!is.na(seed)) { - set.seed(seed) + if (is.na(seed)) { + seed <- sample.int(2147483647L, 1L) } + set.seed(seed) } code } diff --git a/man/position_jitter.Rd b/man/position_jitter.Rd index d7435f14cd..ca6008001d 100644 --- a/man/position_jitter.Rd +++ b/man/position_jitter.Rd @@ -20,7 +20,8 @@ position_jitter(width = NULL, height = NULL, seed = NA) Useful if you need to apply the same jitter twice, e.g., for a point and a corresponding label. The random seed is reset after jittering. -If `NA` (the default value), the current random seed is used. +If `NA` (the default value), the seed is initialised with a random value; +this makes sure that two subsequent calls start with a different seed. Use `NULL` to use the current random seed and also avoid resetting (the behavior of \pkg{ggplot} 2.2.1 and earlier).} } From f222cfcc1e1be5ff0d8eaa650eb13bf58d920374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 7 Feb 2017 14:18:33 +0100 Subject: [PATCH 13/17] extract with_preserve_seed() --- R/utilities.r | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/R/utilities.r b/R/utilities.r index 5cb065de79..4a01235745 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -300,14 +300,22 @@ find_args <- function(...) { dummy_data <- function() data.frame(x = NA) with_seed <- function(seed, code) { - if (!is.null(seed)) { - old_seed <- get_valid_seed() - on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) - if (is.na(seed)) { - seed <- sample.int(2147483647L, 1L) - } - set.seed(seed) + if (is.null(seed)) { + code + } else { + with_preserve_seed({ + if (is.na(seed)) { + seed <- sample.int(2147483647L, 1L) + } + set.seed(seed) + code + }) } +} + +with_preserve_seed <- function(code) { + old_seed <- get_valid_seed() + on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) code } From 7715aa797000261528e783c37b3e1603d2e63ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Tue, 7 Feb 2017 14:21:23 +0100 Subject: [PATCH 14/17] extract function --- R/utilities.r | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/R/utilities.r b/R/utilities.r index 4a01235745..1a4ad7a745 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -304,10 +304,7 @@ with_seed <- function(seed, code) { code } else { with_preserve_seed({ - if (is.na(seed)) { - seed <- sample.int(2147483647L, 1L) - } - set.seed(seed) + set_seed(seed) code }) } @@ -333,6 +330,13 @@ get_seed <- function() { get0(".Random.seed", globalenv(), mode = "integer") } +set_seed <- function(seed) { + if (is.na(seed)) { + seed <- sample.int(2147483647L, 1L) + } + set.seed(seed) +} + # Needed to trigger package loading #' @importFrom tibble tibble NULL From 7774c657bfad009ab64abcd22072d7b42c66b37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Thu, 16 Feb 2017 21:03:55 +0100 Subject: [PATCH 15/17] use withr --- DESCRIPTION | 5 ++++- R/position-jitter.r | 6 +++++- R/utilities.r | 34 ++-------------------------------- 3 files changed, 11 insertions(+), 34 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index f2426e8422..40f350b03f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -16,13 +16,14 @@ Imports: digest, grid, gtable (>= 0.1.1), + lazyeval, MASS, plyr (>= 1.7.1), reshape2, scales (>= 0.4.1), stats, tibble, - lazyeval + withr Suggests: covr, ggplot2movies, @@ -41,6 +42,8 @@ Suggests: rpart, rmarkdown, svglite +Remotes: + jimhester/withr Enhances: sp License: GPL-2 | file LICENSE URL: http://ggplot2.tidyverse.org, https://github.com/tidyverse/ggplot2 diff --git a/R/position-jitter.r b/R/position-jitter.r index 6b8350b299..3d136d7691 100644 --- a/R/position-jitter.r +++ b/R/position-jitter.r @@ -46,6 +46,10 @@ #' geom_point(position = jitter) + #' geom_point(position = jitter, color = "red", aes(am + 0.2, vs + 0.2)) position_jitter <- function(width = NULL, height = NULL, seed = NA) { + if (!is.null(seed) && is.na(seed)) { + seed <- sample.int(.Machine$integer.max, 1L) + } + ggproto(NULL, PositionJitter, width = width, height = height, @@ -72,6 +76,6 @@ PositionJitter <- ggproto("PositionJitter", Position, trans_x <- if (params$width > 0) function(x) jitter(x, amount = params$width) trans_y <- if (params$height > 0) function(x) jitter(x, amount = params$height) - with_seed(params$seed, transform_position(data, trans_x, trans_y)) + with_seed_null(params$seed, transform_position(data, trans_x, trans_y)) } ) diff --git a/R/utilities.r b/R/utilities.r index 1a4ad7a745..36f0ea0485 100644 --- a/R/utilities.r +++ b/R/utilities.r @@ -299,44 +299,14 @@ find_args <- function(...) { # global data dummy_data <- function() data.frame(x = NA) -with_seed <- function(seed, code) { +with_seed_null <- function(seed, code) { if (is.null(seed)) { code } else { - with_preserve_seed({ - set_seed(seed) - code - }) + withr::with_seed(seed, code) } } -with_preserve_seed <- function(code) { - old_seed <- get_valid_seed() - on.exit(assign(".Random.seed", old_seed, globalenv()), add = TRUE) - code -} - -get_valid_seed <- function() { - seed <- get_seed() - if (is.null(seed)) { - # Trigger initialisation of RNG - runif(1L) - seed <- get_seed() - } - seed -} - -get_seed <- function() { - get0(".Random.seed", globalenv(), mode = "integer") -} - -set_seed <- function(seed) { - if (is.na(seed)) { - seed <- sample.int(2147483647L, 1L) - } - set.seed(seed) -} - # Needed to trigger package loading #' @importFrom tibble tibble NULL From d0bf7016c4623108e45d611aea835c16e3778c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 14 Jul 2017 10:03:39 +0200 Subject: [PATCH 16/17] move entry to NEWS.md --- NEWS | 3 --- NEWS.md | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 54284565c7..12746fc39f 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,3 @@ -* `position_jitter()` gains a `seed` argument that allows specifying a random - seed for reproducible jittering (#1996, @krlmlr). - ggplot2 1.0.1 ---------------------------------------------------------------- diff --git a/NEWS.md b/NEWS.md index aba915e5de..18e02dfcc6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -104,6 +104,8 @@ * `ggproto()` produces objects with class `c("ggproto", "gg")`. This was added so that when layers, scales, or other ggproto objects are added together, an informative error message is raised (@jrnold, #2056). +* `position_jitter()` gains a `seed` argument that allows specifying a random seed for reproducible jittering (#1996, @krlmlr). + ### sf From bc38d7372bcd72a6c11acee5b02193ec6457f9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Fri, 14 Jul 2017 10:38:24 +0200 Subject: [PATCH 17/17] add withr as remote --- DESCRIPTION | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 627edcf616..a019b3312b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -48,7 +48,8 @@ Suggests: viridisLite Remotes: hadley/scales, - hadley/svglite + hadley/svglite, + jimhester/withr Enhances: sp License: GPL-2 | file LICENSE URL: http://ggplot2.tidyverse.org, https://github.com/tidyverse/ggplot2