2626# ' or left edges of bins are included in the bin.
2727# ' @param pad If `TRUE`, adds empty bins at either end of x. This ensures
2828# ' frequency polygons touch 0. Defaults to `FALSE`.
29+ # ' @param keep.zeroes Treatment of zero count bins. If `"all"` (default), such
30+ # ' bins are kept as-is. If `"none"`, all zero count bins are filtered out.
31+ # ' If `"inner"` only zero count bins at the flanks are filtered out, but not
32+ # ' in the middle.
2933# ' @eval rd_computed_vars(
3034# ' count = "number of points in bin.",
3135# ' density = "density of points in bin, scaled to integrate to 1.",
@@ -55,6 +59,7 @@ stat_bin <- function(mapping = NULL, data = NULL,
5559 closed = c(" right" , " left" ),
5660 pad = FALSE ,
5761 na.rm = FALSE ,
62+ keep.zeroes = " all" ,
5863 orientation = NA ,
5964 show.legend = NA ,
6065 inherit.aes = TRUE ) {
@@ -77,6 +82,7 @@ stat_bin <- function(mapping = NULL, data = NULL,
7782 pad = pad ,
7883 na.rm = na.rm ,
7984 orientation = orientation ,
85+ keep.zeroes = keep.zeroes ,
8086 ...
8187 )
8288 )
@@ -89,6 +95,10 @@ stat_bin <- function(mapping = NULL, data = NULL,
8995StatBin <- ggproto(" StatBin" , Stat ,
9096 setup_params = function (self , data , params ) {
9197 params $ flipped_aes <- has_flipped_aes(data , params , main_is_orthogonal = FALSE )
98+ params $ keep.zeroes <- arg_match0(
99+ params $ keep.zeroes %|| % " all" ,
100+ c(" all" , " none" , " inner" ), arg_nm = " keep.zeroes"
101+ )
92102
93103 has_x <- ! (is.null(data $ x ) && is.null(params $ x ))
94104 has_y <- ! (is.null(data $ y ) && is.null(params $ y ))
@@ -139,7 +149,7 @@ StatBin <- ggproto("StatBin", Stat,
139149 compute_group = function (data , scales , binwidth = NULL , bins = NULL ,
140150 center = NULL , boundary = NULL ,
141151 closed = c(" right" , " left" ), pad = FALSE ,
142- breaks = NULL , flipped_aes = FALSE ,
152+ breaks = NULL , flipped_aes = FALSE , keep.zeroes = " all " ,
143153 # The following arguments are not used, but must
144154 # be listed so parameters are computed correctly
145155 origin = NULL , right = NULL , drop = NULL ) {
@@ -163,6 +173,14 @@ StatBin <- ggproto("StatBin", Stat,
163173 boundary = boundary , closed = closed )
164174 }
165175 bins <- bin_vector(data [[x ]], bins , weight = data $ weight , pad = pad )
176+
177+ keep <- switch (
178+ keep.zeroes ,
179+ none = bins $ count != 0 ,
180+ inner = inner_runs(bins $ count != 0 ),
181+ TRUE
182+ )
183+ bins <- vec_slice(bins , keep )
166184 bins $ flipped_aes <- flipped_aes
167185 flip_data(bins , flipped_aes )
168186 },
@@ -174,3 +192,12 @@ StatBin <- ggproto("StatBin", Stat,
174192 dropped_aes = " weight" # after statistical transformation, weights are no longer available
175193)
176194
195+ inner_runs <- function (x ) {
196+ rle <- vec_unrep(x )
197+ nruns <- nrow(rle )
198+ inner <- rep(TRUE , nruns )
199+ i <- unique(c(1 , nruns ))
200+ inner [i ] <- inner [i ] & rle $ key [i ]
201+ rep(inner , rle $ times )
202+ }
203+
0 commit comments