Skip to content

Commit f7cb898

Browse files
committed
Make bin_hex and summary_hex consistent.
Fixes #1383
1 parent c6c4665 commit f7cb898

7 files changed

+66
-78
lines changed

DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ Collate:
135135
'guides-.r'
136136
'guides-axis.r'
137137
'guides-grid.r'
138+
'hexbin.R'
138139
'labels.r'
139140
'layer.r'
140141
'limits.r'

NEWS.md

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

3+
* `stat_bin_hex()` and `stat_bin_summary()` now use the same underlying
4+
algorithm so results are consistent (#1383). `stat_bin_hex()` now accepts
5+
a `weight` aesthetic. To be consistent, the output variable from
6+
`stat_bin_hex()` is now value instead of count.
7+
38
* `facet_wrap()` correctly swaps `nrow` and `ncol` for facetting vertically
49
(#1417).
510

R/hexbin.R

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
hex_binwidth <- function(bins = 30, scales) {
2+
c(
3+
diff(scales$x$dimension()) / bins,
4+
diff(scales$y$dimension()) / bins
5+
)
6+
}
7+
8+
hex_bounds <- function(x, binwidth) {
9+
c(
10+
plyr::round_any(min(x), binwidth, floor) - 1e-6,
11+
plyr::round_any(max(x), binwidth, ceiling) + 1e-6
12+
)
13+
}
14+
15+
hexBinSummarise <- function(x, y, z, binwidth, fun = mean, fun.args = list(), drop = TRUE) {
16+
# Convert binwidths into bounds + nbins
17+
xbnds <- hex_bounds(x, binwidth[1])
18+
xbins <- diff(xbnds) / binwidth[1]
19+
20+
ybnds <- hex_bounds(y, binwidth[2])
21+
ybins <- diff(ybnds) / binwidth[2]
22+
23+
# Call hexbin
24+
hb <- hexbin::hexbin(
25+
x, xbnds = xbnds, xbins = xbins,
26+
y, ybnds = ybnds, shape = ybins / xbins,
27+
IDs = TRUE
28+
)
29+
30+
value <- do.call(tapply, c(list(quote(z), quote(hb@cID), quote(fun)), fun.args))
31+
32+
# Convert to data frame
33+
out <- as.data.frame(hexbin::hcell2xy(hb))
34+
out$value <- as.vector(value)
35+
36+
if (drop) out <- stats::na.omit(out)
37+
out
38+
}

R/stat-binhex.r

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -36,54 +36,17 @@ stat_binhex <- stat_bin_hex
3636
#' @usage NULL
3737
#' @export
3838
StatBinhex <- ggproto("StatBinhex", Stat,
39-
default_aes = aes(fill = ..count..),
39+
default_aes = aes(fill = ..value..),
4040

4141
required_aes = c("x", "y"),
4242

4343
compute_group = function(data, scales, binwidth = NULL, bins = 30,
4444
na.rm = FALSE) {
45-
if (is.null(binwidth)) {
46-
binwidth <- c(
47-
diff(scales$x$dimension()) / bins,
48-
diff(scales$y$dimension()) / bins
49-
)
50-
}
45+
try_require("hexbin", "stat_binhex")
5146

52-
hexBin(data$x, data$y, binwidth)
47+
binwidth <- binwidth %||% hex_binwidth(bins, scales)
48+
wt <- data$weight %||% rep(1L, nrow(data))
49+
hexBinSummarise(data$x, data$y, wt, binwidth, sum)
5350
}
5451
)
5552

56-
# Bin 2d plane into hexagons
57-
# Wrapper around \code{\link[hexbin]{hcell2xy}} that returns a data frame
58-
#
59-
# @param x positions
60-
# @param y positions
61-
# @param numeric vector of length 2 giving binwidth in x and y directions
62-
# @keyword internal
63-
hexBin <- function(x, y, binwidth) {
64-
# Convert binwidths into bounds + nbins
65-
xbnds <- c(
66-
plyr::round_any(min(x), binwidth[1], floor) - 1e-6,
67-
plyr::round_any(max(x), binwidth[1], ceiling) + 1e-6
68-
)
69-
xbins <- diff(xbnds) / binwidth[1]
70-
71-
ybnds <- c(
72-
plyr::round_any(min(y), binwidth[2], floor) - 1e-6,
73-
plyr::round_any(max(y), binwidth[2], ceiling) + 1e-6
74-
)
75-
ybins <- diff(ybnds) / binwidth[2]
76-
77-
# Call hexbin
78-
hb <- hexbin::hexbin(
79-
x, xbnds = xbnds, xbins = xbins,
80-
y, ybnds = ybnds, shape = ybins / xbins
81-
)
82-
83-
# Convert to data frame
84-
data.frame(
85-
hexbin::hcell2xy(hb),
86-
count = hb@count,
87-
density = hb@count / sum(hb@count, na.rm = TRUE)
88-
)
89-
}

R/stat-summary-2d.r

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
#' \item \code{y}: vertical position
1313
#' \item \code{z}: value passed to the summary function
1414
#' }
15-
#'
15+
#' @section Computed variables:
16+
#' \describe{
17+
#' \item{x,y}{Location}
18+
#' \item{value}{Value of summary statistic.}
19+
#' }
1620
#' @seealso \code{\link{stat_summary_hex}} for hexagonal summarization.
1721
#' \code{\link{stat_bin2d}} for the binning options.
1822
#' @inheritParams layer

R/stat-summary-hex.r

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -43,41 +43,10 @@ StatSummaryHex <- ggproto("StatSummaryHex", Stat,
4343

4444
compute_group = function(data, scales, binwidth = NULL, bins = 30, drop = TRUE,
4545
fun = "mean", fun.args = list()) {
46-
if (is.null(binwidth)) {
47-
binwidth <- c(
48-
diff(scales$x$dimension()) / bins,
49-
diff(scales$y$dimension()) / bins
50-
)
51-
}
46+
try_require("hexbin", "stat_summary_hex")
5247

53-
# Convert binwidths into bounds + nbins
54-
x <- data$x
55-
y <- data$y
56-
57-
xbnds <- c(
58-
plyr::round_any(min(x), binwidth[1], floor) - 1e-6,
59-
plyr::round_any(max(x), binwidth[1], ceiling) + 1e-6
60-
)
61-
xbins <- diff(xbnds) / binwidth[1]
62-
63-
ybnds <- c(
64-
plyr::round_any(min(y), binwidth[1], floor) - 1e-6,
65-
plyr::round_any(max(y), binwidth[2], ceiling) + 1e-6
66-
)
67-
ybins <- diff(ybnds) / binwidth[2]
68-
69-
# Call hexbin
70-
hb <- hexbin::hexbin(
71-
x, xbnds = xbnds, xbins = xbins,
72-
y, ybnds = ybnds, shape = ybins / xbins,
73-
IDs = TRUE
74-
)
75-
76-
value <- do.call(tapply, c(list(quote(data$z), quote(hb@cID), quote(fun)), fun.args))
77-
78-
# Convert to data frame
79-
ret <- data.frame(hexbin::hcell2xy(hb), value)
80-
if (drop) ret <- stats::na.omit(ret)
81-
ret
48+
binwidth <- binwidth %||% hex_binwidth(bins, scales)
49+
hexBinSummarise(data$x, data$y, data$z, binwidth,
50+
fun = fun, fun.args = fun.args, drop = drop)
8251
}
8352
)

man/stat_summary_2d.Rd

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)