Sortuj wiersze w data.table w kolejności malejącej na kluczu ciągu `order (-x, v)` daje błąd w data.table 1.9.4 lub wcześniej

125

Powiedzmy, że mam następujący data.tablew R:

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

Chcę uporządkować według dwóch kolumn (powiedzmy kolumny xi v). Użyłem tego:

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

Ale teraz chcę to posortować x(w porządku malejącym) i mam następujący kod:

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

Dlatego myślę, że ten błąd wynika z tego class(DT$x)=character. Czy możesz podać mi jakąś sugestię, jak rozwiązać ten problem?

Wiem, że mogę używać DT[order(x,decreasing=TRUE)], ale chcę znać składnię do sortowania według kilku kolumn przy użyciu obu sposobów (niektóre malejące, niektóre zwiększające) w tym samym czasie.

Zauważ, że jeśli używasz, DT[order(-y,v)]wynik jest w porządku, ale jeśli używasz DT[order(-x,v)], jest błąd. Więc moje pytanie brzmi: jak rozwiązać ten błąd?

nhern121
źródło
6
Ciekawe pytanie, ale jeśli pracujesz z dużymi zbiorami danych, prawdopodobnie powinieneś ustawić klucze dla swoich data.tables. Klucze układają dane w kolejności, która maksymalizuje późniejsze indeksowanie, podzbiór, agregację według grup itp. Może to nie być preferowany format drukowania danych, ale często jest to niewielka cena za prędkość, jaką przyniesie .
Josh O'Brien
Jednak wydaje mi się, że DT[order(-x)]nie jest to równoważne stwierdzeniu, setorder(DT, -x)ponieważ setorder()faktycznie działa, DTpodczas gdy inne nie. Równoważne stwierdzenia to DT <- DT [order (-x)] setorder (DT, -x) Jestem bardzo nowy w R, więc proszę poprawić, jeśli się mylę.
jeromeResearch
@jerome Masz rację. Pankil nie powiedział, że są równoważne, więc myślę, że jest w porządku.
Frank
1
Zgadzam się z @smci, że edycja tytułu ma tutaj sens, chociaż zmieniłbym to, aby wskazać, że to pytanie nie jest już aktualne, np. Dodając „in data.table 1.9.4 lub wcześniej” do tytułu, aby ludzie nie kontynuuj lądowanie tutaj z Google, oczekując czegoś innego. Zrobiłem to z jednym z moich pytań stackoverflow.com/questions/30035939/ ...
Frank
1
Nestorggh, nie przywracaj nowego tytułu, chyba że możesz go ulepszyć. „sortowanie wierszy w data.table” prawie nic nie mówiło, że podstawowa funkcjonalność była do dyspozycji. Tytuł musi zawierać informację o Twoim rzeczywistym problemie (wiele kluczy, z których jeden jest zamówieniem). Ważne jest również, że był to znany problem w wersji 1.9.4 i wcześniejszych i nie jest już problemem.
smci

Odpowiedzi:

144

Aktualizacja

data.table v1.9.6 + obsługuje teraz oryginalną próbę OP, a następująca odpowiedź nie jest już potrzebna.


Możesz użyć 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
Matthew Plourde
źródło
1
Jak wskazał poniżej @PankilShah, zostało to naprawione od jakiegoś czasu, a oryginalne podejście OP działa teraz zgodnie z oczekiwaniami. Nie mogłem znaleźć zmiany, ponieważ została naprawiona na poziomie C i nie wiem, czego szukać.
MichaelChirico
1
Fajne dzięki. Wydaje się mało prawdopodobne, że ktoś tu trafi ... ale z drugiej strony ja sam wylądowałem tutaj, szukając w Google czegoś niejasno związanego.
MichaelChirico,
@MichaelChirico właściwie, rutynowo otrzymuję pozytywne głosy na tę odpowiedź, więc bardzo się cieszę, że to zauważyłeś. Nie jestem użytkownikiem data.table i nie nadążam za jego rozwojem.
Matthew Plourde,
Jest to bardzo przydatne do wskazania rzeczywistego numeru wersji (1.9.6?), Więc nie trzeba iść polować w archiwach NEWS.md .
smci
23

Możesz używać tylko -dla wpisów numerycznych, więc możesz zmniejszać i zanegować te, które chcesz, w kolejności rosnącej:

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
James
źródło
3
Podoba mi się ten sposób, chyba że masz dwie characterkolumny i chcesz posortować jedną rosnącą, a drugą malejącą.
Matthew Plourde,
1
@mplourde Myślę, że możesz połączyć swoje rozwiązanie z tym, aby rozwiązać problem, który postawiłeś. Na przykład, można umieścić: DT[order(x,-rank(w),decreasing=TRUE)]skoro xi wsą obie kolumny znaków. Dziękuję Ci!
nhern121,
17

DT[order(-x)]działa zgodnie z oczekiwaniami. Mam data.table w wersji 1.9.4. Może zostało to naprawione w najnowszej wersji.
Sugeruję również setorder(DT, -x)składnię zgodną z poleceniami set * , takimi jak setnames,setkey

Pankil Shah
źródło