Wie sortiere ich einen Vektor anhand der Werte eines anderen


112

Ich habe einen Vektor x, den ich basierend auf der Reihenfolge der Werte in Vektor y sortieren möchte. Die beiden Vektoren sind nicht gleich lang.

x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3)
y <- c(4, 2, 1, 3)

Das erwartete Ergebnis wäre:

[1] 4 4 4 2 2 1 3 3 3

Antworten:


70

Hier ist ein Einzeiler ...

y[sort(order(y)[x])]

[edit:] Dies gliedert sich wie folgt:

order(y)             #We want to sort by y, so order() gives us the sorting order
order(y)[x]          #looks up the sorting order for each x
sort(order(y)[x])    #sorts by that order
y[sort(order(y)[x])] #converts orders back to numbers from orders

1
Das ist sehr prägnant, aber es fällt mir schwer herauszufinden, was dort vor sich geht. Könnten Sie etwas näher darauf eingehen?
Matt Parker

3
Dies ist hübsch und zeigt ein gutes Verständnis der integrierten Funktionen von R. +1
Godeke

6
Im Allgemeinen kann man dies auch dann tun, wenn y keine Permutation von 1: Länge (y) ist. In diesem Fall funktioniert diese Lösung nicht, aber die unten stehende Lösung von gd047, x [order (match (x, y))], funktioniert.
Rahul Savani

5
Ich bin wirklich verblüfft, warum dies 40 positive Stimmen hat. Es schlägt bei so vielen einfachen Variationen von xund fehl y. x <- c(1,4,2); y <- c(1,2,4)zum Beispiel.
E-Mail

1
@thelatemail Ich stimme zu. Stoppen Sie den Wahnsinn und stimmen Sie diese Antwort ab!
Ian Fellows

184

was ist mit diesem

x[order(match(x,y))]

29
Dies ist sehr schön, besser als die akzeptierte Antwort IMHO, da es allgemeiner ist.
Mark

2
Ich würde sogar sagen, dass dies in der Basis GNU-R sein sollte.
katastrophaler Ausfall

Diese Antwort hat bei der Verwendung von Zeichenvektoren sowohl für x als auch für y gut funktioniert. Eine Zerlegung / leichte Ausarbeitung wie in der akzeptierten Antwort hinzuzufügen wäre schön
Außenseiter

4

Sie könnten xin einen geordneten Faktor umrechnen :

x.factor <- factor(x, levels = y, ordered=TRUE)
sort(x)
sort(x.factor)

Offensichtlich kann die Änderung Ihrer Zahlen in Faktoren die Art und Weise, wie Code nachgeschaltet reagiert, radikal verändern x. Aber da Sie uns keinen Kontext darüber gegeben haben, was als nächstes passiert, dachte ich, ich würde dies als Option vorschlagen.


1
Dies sollte die beste Antwort sein, da dies für nicht ganzzahlige Fälle funktionieren würde. oder auch arbeiten, wenn es Werte in xnicht im Sortiervektor ymit geringfügiger Änderung gibt:x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3, 6); y <- c(4, 2, 1, 3); as.numeric(as.character(sort(factor(x, unique(c(y, x))))))
rawr

2

Wie wäre es mit?:

rep(y,table(x)[as.character(y)])

(Ians ist wahrscheinlich noch besser)


2

Falls Sie eine Bestellung für "y" benötigen, egal ob es sich um Zahlen oder Zeichen handelt:

x[order(ordered(x, levels = y))]
4 4 4 2 2 1 3 3 3

Schritt für Schritt:

a <- ordered(x, levels = y) # Create ordered factor from "x" upon order in "y".
[1] 2 2 3 4 1 4 4 3 3
Levels: 4 < 2 < 1 < 3

b <- order(a) # Define "x" order that match to order in "y".
[1] 4 6 7 1 2 5 3 8 9

x[b] # Reorder "x" according to order in "y".
[1] 4 4 4 2 2 1 3 3 3

1

[ Bearbeiten: Natürlich hat Ian den richtigen Ansatz, aber ich werde dies der Nachwelt überlassen.]

Sie können dies ohne Schleifen tun, indem Sie Ihren y-Vektor indizieren. Fügen Sie y einen inkrementellen numerischen Wert hinzu und führen Sie sie zusammen:

y <- data.frame(index=1:length(y), x=y)
x <- data.frame(x=x)
x <- merge(x,y)
x <- x[order(x$index),"x"]
x
[1] 4 4 4 2 2 1 3 3 3

0
x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3)
y <- c(4, 2, 1, 3)
for(i in y) { z <- c(z, rep(i, sum(x==i))) }

Das Ergebnis in z: 4 4 4 2 2 1 3 3 3

Die wichtigen Schritte:

  1. for (i in y) - Schleifen über die interessierenden Elemente.

  2. z <- c (z, ...) - Verkettet nacheinander jeden Unterausdruck

  3. rep (i, sum (x == i)) - Wiederholt i (das aktuelle interessierende Element) sum (x == i) mal (die Häufigkeit, mit der wir i in x gefunden haben).


0

Sie können sqldfes auch mit einer joinFunktion sqlwie folgt verwenden und ausführen:

library(sqldf)
x <- data.frame(x = c(2, 2, 3, 4, 1, 4, 4, 3, 3))
y <- data.frame(y = c(4, 2, 1, 3))

result <- sqldf("SELECT x.x FROM y JOIN x on y.y = x.x")
ordered_x <- result[[1]]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.