Skip to content

Commit 781997f

Browse files
Infer cols from named order in setorderv() (#6932) (#7861)
* updated changes * .. * .. * .. * update tests * refine comment --------- Co-authored-by: Benjamin Schwendinger <benjaminschwe@gmail.com>
1 parent d63559f commit 781997f

4 files changed

Lines changed: 30 additions & 3 deletions

File tree

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242

4343
10. `subset()` method for data.tables supports `drop = TRUE` for consistency to data.frame, [#7859](https://github.com/Rdatatable/data.table/issues/7859). Thanks @MichaelChirico for the report and fix.
4444

45+
11. `setorderv()` now accepts a named vector for the `order` argument. When provided, the names are used to identify the columns, allowing the `cols` argument to be omitted, [#6932](https://github.com/Rdatatable/data.table/issues/6932). Thanks to @MichaelChirico for the suggestion and @venom1204 for the implementation.
46+
4547
### BUG FIXES
4648

4749
1. `fread()` with `skip=0` and `(header=TRUE|FALSE)` no longer skips the first row when it has fewer fields than subsequent rows, [#7463](https://github.com/Rdatatable/data.table/issues/7463). Thanks @emayerhofer for the report and @ben-schwen for the fix.

R/setkey.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ setorder = function(x, ..., na.last=FALSE)
256256

257257
setorderv = function(x, cols = colnames(x), order=1L, na.last=FALSE)
258258
{
259+
if (missing(cols) && !is.null(names(order))) {
260+
cols = names(order)
261+
if (anyDuplicated(cols)) stopf("order argument has named duplicates: %s", brackify(duplicated_values(cols)))
262+
}
259263
if (is.null(cols)) return(x)
260264
if (!is.data.frame(x)) stopf("x must be a data.frame or data.table")
261265
na.last = as.logical(na.last)

inst/tests/tests.Rraw

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21939,3 +21939,16 @@ test(2384.3, print(DT, na.print=".", topn=2, col.names="none", row.names=FALSE,
2193921939
output=c(" .\n e\n ---\n w\n ."))
2194021940
DT = data.table(a=c("x\ny","z"), b=1:2)
2194121941
test(2384.4, print(DT, col.names="none", row.names=FALSE, class=FALSE), output=c(" x\\ny 1\n z 2"))
21942+
21943+
# setorderv() could take order as named column order mapping, #6932
21944+
DT = data.table(a=c(2,1,1,2), b=c("d","c","b","a"), c=c(1,2,1,2))
21945+
m = c(c=-1L, a=1L)
21946+
test(2385.01, setorderv(copy(DT), order=m), setorderv(copy(DT), cols=c("c", "a"), order=m))
21947+
DT=data.table(x=c(2,1,2), y=c(2,1,1))
21948+
test(2385.02, setorderv(DT, order=c(x=1L,y=-1L)), data.table(x=c(1,2,2), y=c(1,2,1)))
21949+
DT = data.table(x=1:3)
21950+
test(2385.03, setorderv(DT, order=c(y=1L)), error="some columns are not in the data.table")
21951+
test(2385.04, setorderv(DT, order=c(x=1L, x=-1L)), error="order argument has named duplicates")
21952+
test(2385.05, setorderv(DT, order=c(x=2L)), error="Must be +1 or -1")
21953+
DT = data.table(a=c(2,1,2), b=3:1)
21954+
test(2385.06, setorderv(copy(DT), order=c(a=1L)), setorderv(copy(DT), cols="a", order=1L))

man/setorder.Rd

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,13 @@ is missing (ex: \code{setorder(x)}), \code{x} is rearranged based on all
4242
columns in ascending order by default. To sort by a column in descending order
4343
prefix the symbol \code{"-"} which means "descending" (\emph{not} "negative", in this context), i.e., \code{setorder(x, a, -b, c)}. The \code{-b} works
4444
when \code{b} is of type \code{character} as well. }
45-
\item{cols}{ A character vector of column names of \code{x} by which to order. By default, sorts over all columns; \code{cols = NULL} will return \code{x} untouched. Do not add \code{"-"} here. Use \code{order} argument instead. }
45+
\item{cols}{ A character vector of column names of \code{x} by which to order. By default, sorts over all columns; \code{cols = NULL} will return \code{x} untouched. Do not add \code{"-"} here. Use \code{order} argument instead. This argument can be omitted if \code{order} is a named vector. }
4646
\item{order}{ An integer vector with only possible values of \code{1} and
4747
\code{-1}, corresponding to ascending and descending order. The length of
4848
\code{order} must be either \code{1} or equal to that of \code{cols}. If
49-
\code{length(order) == 1}, it is recycled to \code{length(cols)}. }
49+
\code{length(order) == 1}, it is recycled to \code{length(cols)}. \code{order}
50+
can also be a named vector, in which case the names are used as \code{cols}
51+
and the \code{cols} argument can be omitted. }
5052
\item{na.last}{ \code{logical}. If \code{TRUE}, missing values in the data are placed last; if \code{FALSE}, they are placed first; if \code{NA} they are removed.
5153
\code{na.last=NA} is valid only for \code{x[order(., na.last)]} and related \code{sort_by(x, .)} (\R \ifelse{html}{\out{&ge;}}{\eqn{\ge}} 4.4.0) and its
5254
default is \code{TRUE}. \code{setorder} and \code{setorderv} only accept
@@ -65,7 +67,9 @@ Note that \code{-b} also works with columns of type \code{character} unlike
6567
\code{\link[base]{order}}, which requires \code{-xtfrm(y)} instead (which is slow).
6668

6769
\code{setorderv} in turn accepts a character vector of column names and an
68-
integer vector of column order separately.
70+
integer vector of column order separately. Additionally, \code{setorderv} can
71+
accept a named integer vector for \code{order}, in which case \code{cols} is
72+
inferred from the names and can be omitted.
6973

7074
Note that \code{\link{setkey}} still requires and will always sort only in
7175
ascending order, and is different from \code{setorder} in that it additionally
@@ -133,6 +137,10 @@ setorder(DT, A, -B)
133137

134138
# same as above, but using setorderv
135139
setorderv(DT, c("A", "B"), c(1, -1))
140+
141+
# infer cols from named order mapping
142+
mapping = c(A = 1L, B = -1L)
143+
setorderv(DT, order = mapping)
136144
}
137145
\keyword{ data }
138146

0 commit comments

Comments
 (0)