Skip to content

Commit 4e3f0e1

Browse files
authored
Pass on binwidth and height to geom (#4671)
1 parent b029aa5 commit 4e3f0e1

File tree

7 files changed

+488
-6
lines changed

7 files changed

+488
-6
lines changed

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# ggplot2 (development version)
22

3+
* `geom_hex()` will now use the binwidth from `stat_bin_hex()` if present,
4+
instead of deriving it (@thomasp85, #4580)
5+
6+
* `geom_hex()` now works on non-linear coordinate systems (@thomasp85)
7+
38
* Fixed a bug throwing errors when trying to render an empty plot with secondary
49
axes (@thomasp85, #4509)
510

R/geom-hex.r

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,36 @@ geom_hex <- function(mapping = NULL, data = NULL,
5656
GeomHex <- ggproto("GeomHex", Geom,
5757
draw_group = function(data, panel_params, coord, lineend = "butt",
5858
linejoin = "mitre", linemitre = 10) {
59-
if (!inherits(coord, "CoordCartesian")) {
60-
abort("geom_hex() only works with Cartesian coordinates")
59+
if (empty(data)) {
60+
return(zeroGrob())
6161
}
6262

63+
# Get hex sizes
64+
if (!is.null(data$width)) {
65+
dx <- data$width[1] / 2
66+
} else {
67+
dx <- resolution(data$x, FALSE)
68+
}
69+
# Adjust for difference in width and height of regular hexagon. 1.15 adjusts
70+
# for the effect of the overlapping range in y-direction on the resolution
71+
# calculation
72+
if (!is.null(data$height)) {
73+
dy <- data$height[1] / sqrt(3) / 2
74+
} else {
75+
dy <- resolution(data$y, FALSE) / sqrt(3) / 2 * 1.15
76+
}
77+
78+
hexC <- hexbin::hexcoords(dx, dy, n = 1)
79+
80+
n <- nrow(data)
81+
82+
data <- data[rep(seq_len(n), each = 6), ]
83+
data$x <- rep.int(hexC$x, n) + data$x
84+
data$y <- rep.int(hexC$y, n) + data$y
85+
6386
coords <- coord$transform(data, panel_params)
64-
ggname("geom_hex", hexGrob(
87+
88+
ggname("geom_hex", polygonGrob(
6589
coords$x, coords$y,
6690
gp = gpar(
6791
col = coords$colour,
@@ -71,7 +95,9 @@ GeomHex <- ggproto("GeomHex", Geom,
7195
lineend = lineend,
7296
linejoin = linejoin,
7397
linemitre = linemitre
74-
)
98+
),
99+
default.units = "native",
100+
id.lengths = rep.int(6, n)
75101
))
76102
},
77103

@@ -97,6 +123,8 @@ GeomHex <- ggproto("GeomHex", Geom,
97123
# @param size vector of hex sizes
98124
# @param gp graphical parameters
99125
# @keyword internal
126+
#
127+
# THIS IS NO LONGER USED BUT LEFT IF CODE SOMEWHERE ELSE RELIES ON IT
100128
hexGrob <- function(x, y, size = rep(1, length(x)), gp = gpar()) {
101129
if (length(y) != length(x)) abort("`x` and `y` must have the same length")
102130

R/hexbin.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ hexBinSummarise <- function(x, y, z, binwidth, fun = mean, fun.args = list(), dr
3636
# Convert to data frame
3737
out <- new_data_frame(hexbin::hcell2xy(hb))
3838
out$value <- as.vector(value)
39+
out$width <- binwidth[1]
40+
out$height <- binwidth[2]
3941

4042
if (drop) out <- stats::na.omit(out)
4143
out

tests/testthat/_snaps/geom-hex/hex-bin-plot-in-polar-coordinates.svg

Lines changed: 183 additions & 0 deletions
Loading

tests/testthat/_snaps/geom-hex/hex-bin-plot-with-sqrt-transformed-y.svg

Lines changed: 181 additions & 0 deletions
Loading
Lines changed: 64 additions & 0 deletions
Loading

tests/testthat/test-geom-hex.R

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,25 @@ test_that("size and linetype are applied", {
1515
geom_hex(color = "red", size = 4, linetype = 2)
1616

1717
gpar <- layer_grob(plot)[[1]]$children[[1]]$gp
18-
expect_equal(gpar$lwd, c(4, 4) * .pt, tolerance = 1e-7)
19-
expect_equal(gpar$lty, c(2, 2), tolerance = 1e-7)
18+
expect_equal(gpar$lwd, rep(4, 12) * .pt, tolerance = 1e-7)
19+
expect_equal(gpar$lty, rep(2, 12), tolerance = 1e-7)
20+
})
21+
22+
test_that("bin size are picked up from stat", {
23+
expect_doppelganger("single hex bin with width and height of 0.1",
24+
ggplot(data.frame(x = 0, y = 0)) +
25+
geom_hex(aes(x = x, y = y), binwidth = c(0.1, 0.1)) +
26+
coord_cartesian(xlim = c(-1, 1), ylim = c(-1, 1))
27+
)
28+
})
29+
30+
test_that("geom_hex works in non-linear coordinate systems", {
31+
p <- ggplot(mpg, aes(displ, hwy)) + geom_hex()
32+
33+
expect_doppelganger("hex bin plot with sqrt-transformed y",
34+
p + coord_trans(y = "sqrt")
35+
)
36+
expect_doppelganger("hex bin plot in polar coordinates",
37+
p + coord_polar()
38+
)
2039
})

0 commit comments

Comments
 (0)