@@ -108,22 +108,16 @@ slice_min.dtplyr_step <- function(.data, order_by, ..., n, prop, with_ties = TRU
108
108
if (missing(order_by )) {
109
109
abort(" argument `order_by` is missing, with no default." )
110
110
}
111
- order_by <- enexpr(order_by )
112
111
113
- ellipsis :: check_dots_empty()
114
- size <- check_slice_size(n , prop )
115
- if (with_ties ) {
116
- j <- switch (size $ type ,
117
- n = expr(.SD [order(!! order_by )][!! smaller_ranks(!! order_by , !! size $ n )]),
118
- prop = expr(.SD [order(!! order_by )][!! smaller_ranks(!! order_by , !! size $ prop * .N )])
119
- )
120
- } else {
121
- j <- switch (size $ type ,
122
- n = expr(head(.SD [order(!! order_by )], !! size $ n )),
123
- prop = expr(head(.SD [order(!! order_by )], !! size $ prop * .N ))
124
- )
125
- }
126
- step_subset_j(.data , j = j )
112
+ slice_min_max(
113
+ .data ,
114
+ order_by = enexpr(order_by ),
115
+ decreasing = FALSE ,
116
+ ... ,
117
+ n = n ,
118
+ prop = prop ,
119
+ with_ties = with_ties
120
+ )
127
121
}
128
122
129
123
# ' @rdname slice.dtplyr_step
@@ -133,30 +127,49 @@ slice_max.dtplyr_step <- function(.data, order_by, ..., n, prop, with_ties = TRU
133
127
if (missing(order_by )) {
134
128
abort(" argument `order_by` is missing, with no default." )
135
129
}
136
- order_by <- enexpr(order_by )
137
130
131
+ slice_min_max(
132
+ .data ,
133
+ order_by = enexpr(order_by ),
134
+ decreasing = TRUE ,
135
+ ... ,
136
+ n = n ,
137
+ prop = prop ,
138
+ with_ties = with_ties
139
+ )
140
+ }
141
+
142
+ slice_min_max <- function (.data , order_by , decreasing , ... , n , prop , with_ties = TRUE ) {
138
143
ellipsis :: check_dots_empty()
139
144
size <- check_slice_size(n , prop )
145
+
146
+ if (decreasing ) {
147
+ order_by <- expr(desc(!! order_by ))
148
+ }
149
+
140
150
if (with_ties ) {
141
- j <- switch (size $ type ,
142
- n = expr(.SD [order(!! order_by , decreasing = TRUE )][!! smaller_ranks(- !! order_by , !! size $ n )]),
143
- prop = expr(.SD [order(!! order_by , decreasing = TRUE )][!! smaller_ranks(- !! order_by , !! size $ prop * .N )])
144
- )
151
+ ties.method <- " min"
145
152
} else {
146
- j <- switch (size $ type ,
147
- n = expr(head(.SD [order(!! order_by , decreasing = TRUE )], !! size $ n )),
148
- prop = expr(head(.SD [order(!! order_by , decreasing = TRUE )], !! size $ prop * .N ))
149
- )
153
+ ties.method <- " first"
150
154
}
151
155
152
- step_subset_j(.data , j = j )
156
+ i <- switch (size $ type ,
157
+ n = expr(!! smaller_ranks(!! order_by , !! size $ n , ties.method = ties.method )),
158
+ prop = expr(!! smaller_ranks(!! order_by , !! size $ prop * .N , ties.method = ties.method ))
159
+ )
160
+
161
+ step_subset_i(.data , i ) %> %
162
+ arrange(!! order_by , .by_group = TRUE )
153
163
}
154
164
155
- smaller_ranks <- function (x , y ) {
165
+ smaller_ranks <- function (x , y , ties.method = " min " ) {
156
166
x <- enexpr(x )
157
167
y <- enexpr(y )
158
168
159
- expr(frankv(!! x , ties.method = " min" , na.last = " keep" ) < = !! y )
169
+ # `frank()` by group is much slower than rank
170
+ # https://github.com/Rdatatable/data.table/issues/3988
171
+ # also https://github.com/Rdatatable/data.table/issues/4284
172
+ expr(rank(!! x , ties.method = !! ties.method , na.last = " keep" ) < = !! y )
160
173
}
161
174
162
175
# ' @importFrom dplyr slice_sample
0 commit comments