20
20
# ' @param segments The number of segments to be used in drawing the ellipse.
21
21
# ' @inheritParams layer
22
22
# ' @inheritParams geom_point
23
+ # ' @eval rd_aesthetics("stat", "ellipse")
23
24
# ' @export
24
25
# ' @examples
25
26
# ' ggplot(faithful, aes(waiting, eruptions)) +
@@ -76,6 +77,8 @@ stat_ellipse <- function(mapping = NULL, data = NULL,
76
77
# ' @export
77
78
StatEllipse <- ggproto(" StatEllipse" , Stat ,
78
79
required_aes = c(" x" , " y" ),
80
+ optional_aes = " weight" ,
81
+ dropped_aes = " weight" ,
79
82
80
83
setup_params = function (data , params ) {
81
84
params $ type <- params $ type %|| % " t"
@@ -96,6 +99,9 @@ calculate_ellipse <- function(data, vars, type, level, segments){
96
99
dfn <- 2
97
100
dfd <- nrow(data ) - 1
98
101
102
+ weight <- data $ weight %|| % rep(1 , nrow(data ))
103
+ weight <- weight / sum(weight )
104
+
99
105
if (! type %in% c(" t" , " norm" , " euclid" )) {
100
106
cli :: cli_inform(" Unrecognized ellipse type" )
101
107
ellipse <- matrix (NA_real_ , ncol = 2 )
@@ -104,11 +110,12 @@ calculate_ellipse <- function(data, vars, type, level, segments){
104
110
ellipse <- matrix (NA_real_ , ncol = 2 )
105
111
} else {
106
112
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 ))
108
115
} else if (type == " norm" ) {
109
- v <- stats :: cov.wt(data [,vars ])
116
+ v <- stats :: cov.wt(data [,vars ], wt = weight )
110
117
} else if (type == " euclid" ) {
111
- v <- stats :: cov.wt(data [,vars ])
118
+ v <- stats :: cov.wt(data [,vars ], wt = weight )
112
119
v $ cov <- diag(rep(min(diag(v $ cov )), 2 ))
113
120
}
114
121
shape <- v $ cov
0 commit comments