19
19
# ' @param reverse If `TRUE`, will reverse the default stacking order.
20
20
# ' This is useful if you're rotating both the plot and legend.
21
21
# ' @family position adjustments
22
+ # ' @eval rd_aesthetics("position", "dodge")
23
+ # '
22
24
# ' @export
23
25
# ' @examples
24
26
# ' ggplot(mtcars, aes(factor(cyl), fill = factor(vs))) +
@@ -104,7 +106,10 @@ PositionDodge <- ggproto("PositionDodge", Position,
104
106
preserve = " total" ,
105
107
orientation = " x" ,
106
108
reverse = NULL ,
109
+ default_aes = aes(order = NULL ),
110
+
107
111
setup_params = function (self , data ) {
112
+
108
113
flipped_aes <- has_flipped_aes(data , default = self $ orientation == " y" )
109
114
check_required_aesthetics(
110
115
if (flipped_aes ) " y|ymin" else " x|xmin" ,
@@ -139,9 +144,22 @@ PositionDodge <- ggproto("PositionDodge", Position,
139
144
140
145
setup_data = function (self , data , params ) {
141
146
data <- flip_data(data , params $ flipped_aes )
147
+
142
148
if (! " x" %in% names(data ) && all(c(" xmin" , " xmax" ) %in% names(data ))) {
143
149
data $ x <- (data $ xmin + data $ xmax ) / 2
144
150
}
151
+
152
+ data $ order <- xtfrm( # xtfrm makes anything 'sortable'
153
+ data $ order %|| % ave(data $ group , data $ x , data $ PANEL , FUN = match_sorted )
154
+ )
155
+ if (params $ reverse ) {
156
+ data $ order <- - data $ order
157
+ }
158
+ if (is.null(params $ n )) { # preserve = "total"
159
+ data $ order <- ave(data $ order , data $ x , data $ PANEL , FUN = match_sorted )
160
+ } else { # preserve = "single"
161
+ data $ order <- match_sorted(data $ order )
162
+ }
145
163
flip_data(data , params $ flipped_aes )
146
164
},
147
165
@@ -179,7 +197,7 @@ pos_dodge <- function(df, width, n = NULL) {
179
197
180
198
# Have a new group index from 1 to number of groups.
181
199
# This might be needed if the group numbers in this set don't include all of 1:n
182
- groupidx <- match( df $ group , unique0 (df $ group ) )
200
+ groupidx <- df $ order % || % match_sorted (df $ group )
183
201
184
202
# Find the center for each group, then use that to calculate xmin and xmax
185
203
df $ x <- df $ x + width * ((groupidx - 0.5 ) / n - 0.5 )
@@ -188,3 +206,7 @@ pos_dodge <- function(df, width, n = NULL) {
188
206
189
207
df
190
208
}
209
+
210
+ match_sorted <- function (x , y = x , ... ) {
211
+ vec_match(x , vec_sort(unique0(y ), ... ))
212
+ }
0 commit comments