diff --git a/NEWS.md b/NEWS.md index c770ac5e16..b297a93bad 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # ggplot2 (development version) +* Fix a bug in `position_jitter()` where different jitters would be applied to + different position aesthetics of the same axis (@thomasp85, #2941) + * `ggsave()` now uses ragg to render raster output if ragg is available (@thomasp85, #4388) diff --git a/R/position-jitter.r b/R/position-jitter.r index 1e314aa2c1..ece4465626 100644 --- a/R/position-jitter.r +++ b/R/position-jitter.r @@ -76,6 +76,17 @@ 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_null(params$seed, transform_position(data, trans_x, trans_y)) + # Make sure x and y jitter is only calculated once for all position aesthetics + x_aes <- intersect(ggplot_global$x_aes, names(data)) + x <- if (length(x_aes) == 0) 0 else data[[x_aes[1]]] + y_aes <- intersect(ggplot_global$y_aes, names(data)) + y <- if (length(y_aes) == 0) 0 else data[[y_aes[1]]] + dummy_data <- new_data_frame(list(x = x, y = y), nrow(data)) + fixed_jitter <- with_seed_null(params$seed, transform_position(dummy_data, trans_x, trans_y)) + x_jit <- fixed_jitter$x - x + y_jit <- fixed_jitter$y - y + + # Apply jitter + transform_position(data, function(x) x + x_jit, function(x) x + y_jit) } )