diff --git a/R/geom-hex.R b/R/geom-hex.R index 0e67b49ad9..71c88a4cf6 100644 --- a/R/geom-hex.R +++ b/R/geom-hex.R @@ -5,10 +5,10 @@ GeomHex <- ggproto("GeomHex", Geom, draw_group = function(self, data, panel_params, coord, lineend = "butt", linejoin = "mitre", linemitre = 10) { - data <- fix_linewidth(data, snake_class(self)) if (empty(data)) { return(zeroGrob()) } + data <- fix_linewidth(data, snake_class(self)) # Get hex sizes if (!is.null(data$width)) { @@ -25,13 +25,12 @@ GeomHex <- ggproto("GeomHex", Geom, dy <- resolution(data$y, FALSE, TRUE) / sqrt(3) / 2 * 1.15 } - hexC <- hexbin::hexcoords(dx, dy, n = 1) - n <- nrow(data) + hexC <- hexbin::hexcoords(dx, dy, n = n) - hexdata <- data[rep(seq_len(n), each = 6), c("x", "y")] - hexdata$x <- rep.int(hexC$x, n) + hexdata$x - hexdata$y <- rep.int(hexC$y, n) + hexdata$y + hexdata <- vec_rep_each(data[c("x", "y", "radius")], times = 6L) + hexdata$x <- hexC$x * hexdata$radius + hexdata$x + hexdata$y <- hexC$y * hexdata$radius + hexdata$y coords <- coord$transform(hexdata, panel_params) @@ -58,6 +57,7 @@ GeomHex <- ggproto("GeomHex", Geom, fill = from_theme(fill %||% col_mix(ink, paper)), linewidth = from_theme(borderwidth), linetype = from_theme(bordertype), + radius = 1, alpha = NA ), @@ -99,5 +99,8 @@ GeomHex <- ggproto("GeomHex", Geom, #' # Or by specifying the width of the bins #' d + geom_hex(binwidth = c(1, 1000)) #' d + geom_hex(binwidth = c(.1, 500)) +#' +#' # The hexagons can be scaled by tuning the radius aesthetic +#' d + geom_hex(aes(radius = after_stat(ncount))) #' } geom_hex <- make_constructor(GeomHex, stat = 'binhex') diff --git a/man/geom_hex.Rd b/man/geom_hex.Rd index fce589bbff..9f295cc507 100644 --- a/man/geom_hex.Rd +++ b/man/geom_hex.Rd @@ -175,6 +175,9 @@ d + geom_hex(bins = 30) # Or by specifying the width of the bins d + geom_hex(binwidth = c(1, 1000)) d + geom_hex(binwidth = c(.1, 500)) + +# The hexagons can be scaled by tuning the radius aesthetic +d + geom_hex(aes(radius = after_stat(ncount))) } } \seealso{ @@ -192,6 +195,7 @@ d + geom_hex(binwidth = c(.1, 500)) • \tab \code{\link[=aes_group_order]{group}} \tab → inferred \cr • \tab \code{\link[=aes_linetype_size_shape]{linetype}} \tab → via \code{theme()} \cr • \tab \code{\link[=aes_linetype_size_shape]{linewidth}} \tab → via \code{theme()} \cr + • \tab \code{radius} \tab → \code{1} \cr } \code{stat_binhex()} understands the following aesthetics. Required aesthetics are displayed in bold and defaults are displayed for optional aesthetics: diff --git a/tests/testthat/_snaps/geom-hex/hexes-with-different-sizes.svg b/tests/testthat/_snaps/geom-hex/hexes-with-different-sizes.svg new file mode 100644 index 0000000000..134814cb90 --- /dev/null +++ b/tests/testthat/_snaps/geom-hex/hexes-with-different-sizes.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +-1.0 +-0.5 +0.0 +0.5 +1.0 + + + + + + + + + + +0 +1 +2 +3 +4 +x +y +hexes with different sizes + + diff --git a/tests/testthat/test-geom-hex.R b/tests/testthat/test-geom-hex.R index 498f00d407..516bc8a060 100644 --- a/tests/testthat/test-geom-hex.R +++ b/tests/testthat/test-geom-hex.R @@ -27,6 +27,17 @@ test_that("bin size are picked up from stat", { geom_hex(aes(x = x, y = y), binwidth = c(0.1, 0.1)) + coord_cartesian(xlim = c(-1, 1), ylim = c(-1, 1)) ) + + expect_doppelganger( + "hexes with different sizes", + ggplot(data.frame(x = 1:3, y = 0, r = (1:3)/6)) + + geom_hex( + aes(x = x, y = y, radius = r), + stat = "identity" + ) + + coord_cartesian(xlim = c(0, 4), y = c(-1, 1)) + ) + }) test_that("geom_hex works in non-linear coordinate systems", {