Skip to content

Commit aa6ee95

Browse files
authored
Weighted ellipses (#6186)
* add `weight` aesthetic * add news bullet * document aesthetics
1 parent ed1b80d commit aa6ee95

File tree

3 files changed

+23
-3
lines changed

3 files changed

+23
-3
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@
267267
* Standardised the calculation of `width`, which are now implemented as
268268
aesthetics (@teunbrand, #2800).
269269
* Stricter check on `register_theme_elements(element_tree)` (@teunbrand, #6162)
270+
* Added `weight` aesthetic for `stat_ellipse()` (@teunbrand, #5272)
270271

271272
# ggplot2 3.5.1
272273

R/stat-ellipse.R

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#' @param segments The number of segments to be used in drawing the ellipse.
2121
#' @inheritParams layer
2222
#' @inheritParams geom_point
23+
#' @eval rd_aesthetics("stat", "ellipse")
2324
#' @export
2425
#' @examples
2526
#' ggplot(faithful, aes(waiting, eruptions)) +
@@ -76,6 +77,8 @@ stat_ellipse <- function(mapping = NULL, data = NULL,
7677
#' @export
7778
StatEllipse <- ggproto("StatEllipse", Stat,
7879
required_aes = c("x", "y"),
80+
optional_aes = "weight",
81+
dropped_aes = "weight",
7982

8083
setup_params = function(data, params) {
8184
params$type <- params$type %||% "t"
@@ -96,6 +99,9 @@ calculate_ellipse <- function(data, vars, type, level, segments){
9699
dfn <- 2
97100
dfd <- nrow(data) - 1
98101

102+
weight <- data$weight %||% rep(1, nrow(data))
103+
weight <- weight / sum(weight)
104+
99105
if (!type %in% c("t", "norm", "euclid")) {
100106
cli::cli_inform("Unrecognized ellipse type")
101107
ellipse <- matrix(NA_real_, ncol = 2)
@@ -104,11 +110,12 @@ calculate_ellipse <- function(data, vars, type, level, segments){
104110
ellipse <- matrix(NA_real_, ncol = 2)
105111
} else {
106112
if (type == "t") {
107-
v <- MASS::cov.trob(data[,vars])
113+
# Prone to convergence problems when `sum(weight) != nrow(data)`
114+
v <- MASS::cov.trob(data[,vars], wt = weight * nrow(data))
108115
} else if (type == "norm") {
109-
v <- stats::cov.wt(data[,vars])
116+
v <- stats::cov.wt(data[,vars], wt = weight)
110117
} else if (type == "euclid") {
111-
v <- stats::cov.wt(data[,vars])
118+
v <- stats::cov.wt(data[,vars], wt = weight)
112119
v$cov <- diag(rep(min(diag(v$cov)), 2))
113120
}
114121
shape <- v$cov

man/stat_ellipse.Rd

Lines changed: 12 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)