2424# ' @eval rd_computed_vars(
2525# ' density = "density estimate.",
2626# ' count = "density * number of points - useful for stacked density plots.",
27+ # ' wdensity = "density * sum of weights. In absence of weights, the same as
28+ # ' `count`.",
2729# ' scaled = "density estimate, scaled to maximum of 1.",
2830# ' n = "number of points.",
2931# ' ndensity = "alias for `scaled`, to mirror the syntax of [`stat_bin()`]."
@@ -113,17 +115,19 @@ StatDensity <- ggproto("StatDensity", Stat,
113115compute_density <- function (x , w , from , to , bw = " nrd0" , adjust = 1 ,
114116 kernel = " gaussian" , n = 512 ,
115117 bounds = c(- Inf , Inf )) {
116- nx <- length(x )
118+ nx <- w_sum <- length(x )
117119 if (is.null(w )) {
118120 w <- rep(1 / nx , nx )
119121 } else {
120- w <- w / sum(w )
122+ w_sum <- sum(w )
123+ w <- w / w_sum
121124 }
122125
123126 # Adjust data points and weights to all fit inside bounds
124127 sample_data <- fit_data_to_bounds(bounds , x , w )
125128 x <- sample_data $ x
126129 w <- sample_data $ w
130+ w_sum <- sample_data $ w_sum * w_sum
127131 nx <- length(x )
128132
129133 # if less than 2 points return data frame of NAs and a warning
@@ -135,6 +139,7 @@ compute_density <- function(x, w, from, to, bw = "nrd0", adjust = 1,
135139 scaled = NA_real_ ,
136140 ndensity = NA_real_ ,
137141 count = NA_real_ ,
142+ wdensity = NA_real_ ,
138143 n = NA_integer_ ,
139144 .size = 1
140145 ))
@@ -158,6 +163,7 @@ compute_density <- function(x, w, from, to, bw = "nrd0", adjust = 1,
158163 scaled = dens $ y / max(dens $ y , na.rm = TRUE ),
159164 ndensity = dens $ y / max(dens $ y , na.rm = TRUE ),
160165 count = dens $ y * nx ,
166+ wdensity = dens $ y * w_sum ,
161167 n = nx ,
162168 .size = length(dens $ x )
163169 )
@@ -166,7 +172,7 @@ compute_density <- function(x, w, from, to, bw = "nrd0", adjust = 1,
166172# Check if all data points are inside bounds. If not, warn and remove them.
167173fit_data_to_bounds <- function (bounds , x , w ) {
168174 is_inside_bounds <- (bounds [1 ] < = x ) & (x < = bounds [2 ])
169-
175+ w_sum <- 1
170176 if (! all(is_inside_bounds )) {
171177 cli :: cli_warn(" Some data points are outside of `bounds`. Removing them." )
172178 x <- x [is_inside_bounds ]
@@ -177,7 +183,7 @@ fit_data_to_bounds <- function(bounds, x, w) {
177183 }
178184 }
179185
180- return (list (x = x , w = w ))
186+ return (list (x = x , w = w , w_sum = w_sum ))
181187}
182188
183189# Update density estimation to mitigate boundary effect at known `bounds`:
0 commit comments