Das Sortieren von Zeilen in data.table in absteigender Reihenfolge auf dem Zeichenfolgenschlüssel `order (-x, v)` führt zu einem Fehler in data.table 1.9.4 oder früher

125

Angenommen, ich habe Folgendes data.tablein R:

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

Ich möchte es nach zwei Spalten ordnen (sagen wir Spalten xund v). Ich habe das benutzt:

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

Aber jetzt möchte ich es sortieren x(in absteigender Reihenfolge) und den folgenden Code haben:

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

Daher denke ich, dass dieser Fehler auf die Tatsache zurückzuführen ist, dass class(DT$x)=character. Können Sie mir einen Vorschlag machen, um dieses Problem zu lösen?

Ich weiß, dass ich verwenden kann DT[order(x,decreasing=TRUE)], aber ich möchte die Syntax kennen, nach der mehrere Spalten gleichzeitig in beide Richtungen (einige abnehmend, andere zunehmend) sortiert werden.

Beachten Sie, dass bei Verwendung DT[order(-y,v)]das Ergebnis in Ordnung ist, bei Verwendung DT[order(-x,v)]jedoch ein Fehler auftritt. Meine Frage lautet also: Wie kann dieser Fehler behoben werden?

nhern121
quelle
6
Interessante Frage, aber wenn Sie mit großen Datenmengen arbeiten, sollten Sie wahrscheinlich Schlüssel für Ihre data.tables festlegen. Mit Schlüsseln werden Ihre Daten in eine Reihenfolge gebracht, in der die nachfolgende Indizierung, Teilmenge, Aggregation nach Gruppen usw. maximiert wird. Dies ist möglicherweise nicht Ihr bevorzugtes Format zum Drucken der Daten, aber es ist oft ein geringer Preis für die Geschwindigkeit, die Sie damit erzielen .
Josh O'Brien
Es scheint mir jedoch, dass dies DT[order(-x)]keine äquivalente Aussage ist, setorder(DT, -x)weil es setorder()tatsächlich wirkt, DTwährend das andere nicht handelt. Äquivalente Aussagen wären DT <- DT [order (-x)] setorder (DT, -x) Ich bin sehr neu in R, bitte korrigieren Sie, wenn ich mich irre.
JeromeResearch
@ Jerome Du bist richtig. Pankil hat nicht gesagt, dass sie gleichwertig sind, also denke ich, dass es in Ordnung ist, wie es ist.
Frank
1
Ich stimme @smci zu, dass eine Titelbearbeitung hier sinnvoll ist, obwohl ich sie ändern würde, um anzuzeigen, dass diese Frage nicht mehr relevant ist, z. B. indem ich dem Titel "in data.table 1.9.4 oder früher" hinzufüge, damit die Leute dies nicht tun Lande hier weiter von Google und erwarte etwas anderes. Ich tat dies mit einer meiner Fragen stackoverflow.com/questions/30035939/…
Frank
1
Nestorggh, bitte setzen Sie den neuen Titel nicht zurück, es sei denn, Sie können ihn verbessern. "Zeilen in data.table sortieren" sagte fast nichts, dass die Grundfunktionalität für yonks da war. Der Titel muss Ihr aktuelles Problem erwähnen (mehrere Schlüssel, bei denen einer in der Reihenfolge dekr ist). Wichtig ist auch, dass dies ein bekanntes Problem in 1.9.4 und früher war und kein Problem mehr ist.
smci

Antworten:

144

Aktualisieren

data.table v1.9.6 + unterstützt jetzt den ursprünglichen Versuch von OP und die folgende Antwort ist nicht mehr erforderlich.


Sie können verwenden 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
quelle
1
Wie von @PankilShah weiter unten ausgeführt, wurde dies seit einiger Zeit behoben und der ursprüngliche Ansatz von OP funktioniert nun wie erwartet. Ich konnte das Commit nicht finden, da es auf der C-Ebene behoben wurde und ich nicht weiß, wonach ich suchen soll.
MichaelChirico
1
Cool, danke. Es ist unwahrscheinlich, dass irgendjemand hier landen würde ... aber andererseits bin ich selbst hier gelandet, weil ich etwas vage googelt habe.
MichaelChirico
@MichaelChirico Eigentlich bekomme ich regelmäßig Up-Votes für diese Antwort, also bin ich wirklich froh, dass Sie darauf hingewiesen haben. Ich bin nicht wirklich ein Benutzer von data.table und habe mit seiner Entwicklung nicht Schritt gehalten .
Matthew Plourde
Es ist sehr nützlich, die tatsächliche Versionsnummer (1.9.6?) Anzugeben, damit wir nicht in den Archiven von NEWS.md auf die Jagd gehen müssen .
smci
23

Sie können nur -numerische Einträge verwenden, sodass Sie die gewünschten Einträge in aufsteigender Reihenfolge verringern und negieren können:

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
quelle
3
Ich mag diesen Weg, es sei denn, Sie haben zwei characterSpalten und möchten eine zunehmende und eine abnehmende sortieren.
Matthew Plourde
1
@mplourde Ich denke, Sie können Ihre Lösung mit dieser kombinieren, um das von Ihnen aufgeworfene Problem anzugehen. Zum Beispiel können Sie setzen: DT[order(x,-rank(w),decreasing=TRUE)]vorausgesetzt, dass xund wbeide Zeichenspalten sind. Danke dir!
Nhern121
17

DT[order(-x)]funktioniert wie erwartet. Ich habe data.table Version 1.9.4. Möglicherweise wurde dies in einer neueren Version behoben.
Außerdem schlage ich die setorder(DT, -x)Syntax vor, die den set * -Befehlen entspricht, wie z setnames.setkey

Pankil Shah
quelle