4
4
# ' @param scale if "area" (default), all violins have the same area (before trimming
5
5
# ' the tails). If "count", areas are scaled proportionally to the number of
6
6
# ' observations. If "width", all violins have the same maximum width.
7
+ # ' @param drop Whether to discard groups with less than 2 observations
8
+ # ' (`TRUE`, default) or keep such groups for position adjustment purposes
9
+ # ' (`FALSE`).
7
10
# '
8
11
# ' @eval rd_computed_vars(
9
12
# ' density = "Density estimate.",
@@ -28,6 +31,7 @@ stat_ydensity <- function(mapping = NULL, data = NULL,
28
31
kernel = " gaussian" ,
29
32
trim = TRUE ,
30
33
scale = " area" ,
34
+ drop = TRUE ,
31
35
na.rm = FALSE ,
32
36
orientation = NA ,
33
37
show.legend = NA ,
@@ -48,6 +52,7 @@ stat_ydensity <- function(mapping = NULL, data = NULL,
48
52
kernel = kernel ,
49
53
trim = trim ,
50
54
scale = scale ,
55
+ drop = drop ,
51
56
na.rm = na.rm ,
52
57
...
53
58
)
@@ -72,10 +77,20 @@ StatYdensity <- ggproto("StatYdensity", Stat,
72
77
extra_params = c(" na.rm" , " orientation" ),
73
78
74
79
compute_group = function (self , data , scales , width = NULL , bw = " nrd0" , adjust = 1 ,
75
- kernel = " gaussian" , trim = TRUE , na.rm = FALSE , flipped_aes = FALSE ) {
80
+ kernel = " gaussian" , trim = TRUE , na.rm = FALSE ,
81
+ drop = TRUE , flipped_aes = FALSE ) {
76
82
if (nrow(data ) < 2 ) {
77
- cli :: cli_warn(" Groups with fewer than two data points have been dropped." )
78
- return (data_frame0())
83
+ if (isTRUE(drop )) {
84
+ cli :: cli_warn(c(
85
+ " Groups with fewer than two datapoints have been dropped." ,
86
+ i = paste0(
87
+ " Set {.code drop = FALSE} to consider such groups for position " ,
88
+ " adjustment purposes."
89
+ )))
90
+ return (data_frame0())
91
+ }
92
+ ans <- data_frame0(x = data $ x , n = nrow(data ))
93
+ return (ans )
79
94
}
80
95
range <- range(data $ y , na.rm = TRUE )
81
96
modifier <- if (trim ) 0 else 3
@@ -97,21 +112,27 @@ StatYdensity <- ggproto("StatYdensity", Stat,
97
112
98
113
compute_panel = function (self , data , scales , width = NULL , bw = " nrd0" , adjust = 1 ,
99
114
kernel = " gaussian" , trim = TRUE , na.rm = FALSE ,
100
- scale = " area" , flipped_aes = FALSE ) {
115
+ scale = " area" , flipped_aes = FALSE , drop = TRUE ) {
101
116
data <- flip_data(data , flipped_aes )
102
117
data <- ggproto_parent(Stat , self )$ compute_panel(
103
118
data , scales , width = width , bw = bw , adjust = adjust , kernel = kernel ,
104
- trim = trim , na.rm = na.rm
119
+ trim = trim , na.rm = na.rm , drop = drop
105
120
)
121
+ if (! drop && any(data $ n < 2 )) {
122
+ cli :: cli_warn(
123
+ " Cannot compute density for groups with fewer than two datapoints."
124
+ )
125
+ }
106
126
107
127
# choose how violins are scaled relative to each other
108
128
data $ violinwidth <- switch (scale ,
109
129
# area : keep the original densities but scale them to a max width of 1
110
130
# for plotting purposes only
111
- area = data $ density / max(data $ density ),
131
+ area = data $ density / max(data $ density , na.rm = TRUE ),
112
132
# count: use the original densities scaled to a maximum of 1 (as above)
113
133
# and then scale them according to the number of observations
114
- count = data $ density / max(data $ density ) * data $ n / max(data $ n ),
134
+ count = data $ density / max(data $ density , na.rm = TRUE ) *
135
+ data $ n / max(data $ n ),
115
136
# width: constant width (density scaled to a maximum of 1)
116
137
width = data $ scaled
117
138
)
0 commit comments