Ich habe eine numerische Liste:
myList = [1, 2, 3, 100, 5]
Nun, wenn ich diese Liste sortiere, um zu erhalten [1, 2, 3, 5, 100]
. Was ich möchte, sind die Indizes der Elemente aus der ursprünglichen Liste in der sortierten Reihenfolge, dh [0, 1, 2, 4, 3]
--- ala MATLABs Sortierfunktion, die sowohl Werte als auch Indizes zurückgibt.
Antworten:
Wenn Sie numpy verwenden, steht Ihnen die Funktion argsort () zur Verfügung:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
Dies gibt die Argumente zurück, die das Array oder die Liste sortieren würden.
quelle
So etwas wie das nächste:
enumerate(myList)
gibt Ihnen eine Liste mit Tupeln von (Index, Wert):Sie sortieren die Liste, indem Sie sie an übergeben
sorted
und eine Funktion zum Extrahieren des Sortierschlüssels angeben (das zweite Element jedes Tupels; dafürlambda
ist das vorgesehen. Schließlich wird der ursprüngliche Index jedes sortierten Elements mithilfe des[i[0] for i in ...]
Listenverständnisses extrahiert .quelle
itemgetter(1)
anstelle der Lambda-Funktion verwendenitemgetter
Funktion imoperator
Modul, FYI. Also machfrom operator import itemgetter
es.sorted_items, sorted_inds = zip(*sorted([(i,e) for i,e in enumerate(my_list)], key=itemgetter(1)))
x = [3,1,2]; numpy.argsort(x)
ergibt [1,2,0].quelle
Die Antworten mit
enumerate
sind nett, aber ich persönlich mag das Lambda nicht, das verwendet wird, um nach dem Wert zu sortieren. Im Folgenden werden nur der Index und der Wert umgekehrt und sortiert. Es wird also zuerst nach Wert und dann nach Index sortiert.quelle
Aktualisierte Antwort mit
enumerate
unditemgetter
:Zippen Sie die Listen zusammen: Das erste Element im Tupel enthält den Index, das zweite den Wert (sortieren Sie ihn dann nach dem zweiten Wert des Tupels
x[1]
, x ist das Tupel).Oder mit
itemgetter
aus demoperator
Modul`:quelle
Ich habe diese mit perfplot (einem meiner Projekte) schnell überprüft und festgestellt, dass es schwierig ist, etwas anderes als numpy zu empfehlen (beachten Sie die Protokollskala):
Code zur Reproduktion der Handlung:
quelle
Wenn Sie numpy nicht verwenden möchten,
ist am schnellsten, wie hier gezeigt .
quelle
Im Wesentlichen müssen Sie eine durchführen
argsort
. Welche Implementierung Sie benötigen, hängt davon ab, ob Sie externe Bibliotheken (z. B. NumPy) verwenden möchten oder ob Sie Pure-Python ohne Abhängigkeiten bleiben möchten.Die Frage, die Sie sich stellen müssen, lautet: Wollen Sie die
Leider macht das Beispiel in der Frage nicht klar, was gewünscht wird, da beide das gleiche Ergebnis liefern:
Auswahl der
argsort
ImplementierungWenn Sie NumPy zur Verfügung haben, können Sie einfach die Funktion
numpy.argsort
oder Methode verwendennumpy.ndarray.argsort
.Eine Implementierung ohne NumPy wurde bereits in einigen anderen Antworten erwähnt, daher werde ich hier nur die schnellste Lösung gemäß der Benchmark-Antwort zusammenfassen
Abrufen der Indizes, die das Array / die Liste sortieren würden
Um die Indizes zu erhalten, die das Array / die Liste sortieren würden, können Sie einfach
argsort
das Array oder die Liste aufrufen . Ich verwende hier die NumPy-Versionen, aber die Python-Implementierung sollte die gleichen Ergebnisse liefernDas Ergebnis enthält die Indizes, die zum Abrufen des sortierten Arrays erforderlich sind.
Da das sortierte Array
[1, 2, 3, 4]
das argsortierte Array wäre, enthält es die Indizes dieser Elemente im Original.1
und befindet sich am Index1
im Original, sodass das erste Element des Ergebnisses ist1
.2
ist2
im Original im Index, also ist das zweite Element des Ergebnisses2
.3
ist0
im Original im Index, also ist das dritte Element des Ergebnisses0
.4
und der Index3
im Original, also das letzte Element des Ergebnisses3
.Abrufen der Indizes, die die Elemente im sortierten Array / in der sortierten Liste haben würden
In diesem Fall müssten Sie sich
argsort
zweimal bewerben :In diesem Fall :
3
der drittgrößte Wert, sodass es einen Index2
im sortierten Array / der sortierten Liste hat, also das erste Element2
.1
der kleinste Wert, sodass es einen Index0
im sortierten Array / der sortierten Liste hat, also das zweite Element0
.2
der zweitkleinste Wert, sodass es einen Index1
im sortierten Array / der sortierten Liste hat, also das dritte Element1
.4
der größte Wert, sodass es einen Index3
im sortierten Array / der sortierten Liste hat, also das letzte Element3
.quelle
Die anderen Antworten sind falsch.
argsort
Einmal laufen ist nicht die Lösung. Zum Beispiel der folgende Code:Renditen,
array([1, 2, 0], dtype=int64)
die wir nicht wollen.Die Antwort sollte sein,
argsort
zweimal zu laufen :gibt
array([2, 0, 1], dtype=int64)
wie erwartet.quelle
x[2]
(3) das kleinste Element undx[1]
(1) das größte Element (da das Sortieren von ganzen Zahlen sie vom kleinsten zum größten Wert ordnet). Mit dem OPs-Beispielnp.argsort([1, 2, 3, 100, 5])
ergibt sich auch eine einzelne Renditearray([0, 1, 2, 4, 3])
, bei der es sich anscheinend um die vom OP gewünschten Indizes handelt.arr = [1,2,3,100, 5, 9] res = np.argsort(arr) print(res)
, bekommen wir[0 1 2 4 5 3]
was falsch ist.arr[res]
Erträgearray([ 1, 2, 3, 5, 9, 100])
, die vollkommen in Ordnung zu sein scheinen, da das resultierende Array in (zunehmender) Reihenfolge ist.arr=[1,2,3,100, 5, 9]
, ich erwarte die Ausgabeinds=[0,1,2,5,3,4]
, weil dies die Reihenfolge ist, in der Sie die Elemente (zunehmend) ordnen - 1 ist an der 0er Stelle, 2 an der 1. Stelle, ...., 5 an der 3. Platz und 9 auf dem 4. Platz. Um diese Ausgabe (inds
) zu erhalten, muss ichargsort
, wie bereits erwähnt, zweimal ausgeführt werden.sort
möchte das OP die andere Funktionalität, wie sienp.argsort
normalerweise verwendet wird (wo manarr[np.argsort[arr]]
das sortierte Array erhalten kann, wie im letzten MATLAB-Beispiel). Ihre Antwort gilt stattdessen für diesen Fall / diese Frage .Importiere numpy als np
FÜR INDEX
argsort Gibt die Indizes von S in sortierter Reihenfolge zurück
FÜR WERT
quelle
Wir werden ein weiteres Array von Indizes von 0 bis n-1 erstellen. Dann komprimieren Sie dieses in das ursprüngliche Array und sortieren es dann anhand der ursprünglichen Werte
`
quelle