@@ -141,6 +141,9 @@ StatDensity2d <- ggproto("StatDensity2d", Stat,
141141 check_installed(" MASS" , reason = " for calculating 2D density." )
142142 # first run the regular layer calculation to infer densities
143143 data <- ggproto_parent(Stat , self )$ compute_layer(data , params , layout )
144+ if (empty(data )) {
145+ return (data_frame0())
146+ }
144147
145148 # if we're not contouring we're done
146149 if (! isTRUE(params $ contour %|| % TRUE )) return (data )
@@ -178,10 +181,8 @@ StatDensity2d <- ggproto("StatDensity2d", Stat,
178181
179182 compute_group = function (data , scales , na.rm = FALSE , h = NULL , adjust = c(1 , 1 ),
180183 n = 100 , ... ) {
181- if (is.null(h )) {
182- h <- c(MASS :: bandwidth.nrd(data $ x ), MASS :: bandwidth.nrd(data $ y ))
183- h <- h * adjust
184- }
184+
185+ h <- precompute_2d_bw(data $ x , data $ y , h = h , adjust = adjust )
185186
186187 # calculate density
187188 dens <- MASS :: kde2d(
@@ -214,3 +215,27 @@ StatDensity2dFilled <- ggproto("StatDensity2dFilled", StatDensity2d,
214215 contour_type = " bands"
215216)
216217
218+ precompute_2d_bw <- function (x , y , h = NULL , adjust = 1 ) {
219+
220+ if (is.null(h )) {
221+ # Note: MASS::bandwidth.nrd is equivalent to stats::bw.nrd * 4
222+ h <- c(MASS :: bandwidth.nrd(x ), MASS :: bandwidth.nrd(y ))
223+ # Handle case when when IQR == 0 and thus regular nrd bandwidth fails
224+ if (h [1 ] == 0 && length(x ) > 1 ) h [1 ] <- bw.nrd0(x ) * 4
225+ if (h [2 ] == 0 && length(y ) > 1 ) h [2 ] <- bw.nrd0(y ) * 4
226+ h <- h * adjust
227+ }
228+
229+ check_numeric(h )
230+ check_length(h , 2L )
231+
232+ if (any(is.na(h ) | h < = 0 )) {
233+ cli :: cli_abort(c(
234+ " The bandwidth argument {.arg h} must contain numbers larger than 0." ,
235+ i = " Please set the {.arg h} argument to stricly positive numbers manually."
236+ ))
237+ }
238+
239+ h
240+ }
241+
0 commit comments