Sort rows in data.table in decreasing order on string key `order(-x,v)` gives error on data.table 1.9.4 or earlier

209,206

Solution 1

Update

data.table v1.9.6+ now supports OP's original attempt and the following answer is no longer necessary.


You can use DT[order(-rank(x), y)].

   x y v
1: c 1 7
2: c 3 8
3: c 6 9
4: b 1 1
5: b 3 2
6: b 6 3
7: a 1 4
8: a 3 5
9: a 6 6

Solution 2

You can only use - on the numeric entries, so you can use decreasing and negate the ones you want in increasing order:

DT[order(x,-v,decreasing=TRUE),]
      x y v
 [1,] c 1 7
 [2,] c 3 8
 [3,] c 6 9
 [4,] b 1 1
 [5,] b 3 2
 [6,] b 6 3
 [7,] a 1 4
 [8,] a 3 5
 [9,] a 6 6

Solution 3

DT[order(-x)] works as expected. I have data.table version 1.9.4. Maybe this was fixed in a recent version.
Also, I suggest the setorder(DT, -x) syntax in keeping with the set* commands like setnames, setkey

Share:
209,206
nhern121
Author by

nhern121

PhD candidate in CS

Updated on January 25, 2020

Comments

  • nhern121
    nhern121 over 4 years

    Let's say I have the following data.table in R:

      library(data.table)
      DT = data.table(x=rep(c("b","a","c"),each=3), y=c(1,3,6), v=1:9)
    

    I want to order it by two columns (say columns x and v). I used this:

     DT[order(x,v)] # sorts first by x then by v (both in ascending order)
    

    But now, I want to sort it by x (in decreasing order) and have the following code:

      DT[order(-x)] #Error in -x : invalid argument to unary operator
    

    Therefore, I think this error is due to the fact that class(DT$x)=character. Could you give me any suggestion in order to solve this issue?

    I know I can use DT[order(x,decreasing=TRUE)], but I want to know the syntax to sort by several columns using both ways (some decreasing, some increasing) at the same time.

    Note that if you use DT[order(-y,v)] the result is ok, but if you use DT[order(-x,v)] there is an error. So, my question is: how to solve this error?

  • Matthew Plourde
    Matthew Plourde over 11 years
    I like this way, unless you have two character columns and you want to sort one increasing and the other decreasing.
  • nhern121
    nhern121 over 11 years
    @mplourde I think you can combine your solution with this one to tackle the problem you have posed. For instance, you can put: DT[order(x,-rank(w),decreasing=TRUE)] given that x and w are both character columns. Thank you!
  • MichaelChirico
    MichaelChirico about 8 years
    As pointed out by @PankilShah below this has been fixed for some time and OP's original approach now works as expected. I couldn't find the commit since it was fixed on the C level and I don't know what to search for.
  • MichaelChirico
    MichaelChirico about 8 years
    Cool, thanks. It seems unlikely that anyone would end up here... but on the other hand I myself ended up here from googling something vaguely-related.
  • Matthew Plourde
    Matthew Plourde about 8 years
    @MichaelChirico actually, I routinely get up-votes for this answer, so I'm really glad you pointed this out. I'm not really a data.table user and haven't been keeping up with its development.
  • smci
    smci about 6 years
    It's very useful to state the actual release number (1.9.6?), so we don't have to go hunt in the archives of NEWS.md.