Ich habe ein Array von Zahlen und möchte ein weiteres Array erstellen, das den Rang jedes Elements im ersten Array darstellt. Ich benutze Python und NumPy.
Beispielsweise:
array = [4,2,7,1]
ranks = [2,1,3,0]
Hier ist die beste Methode, die ich mir ausgedacht habe:
array = numpy.array([4,2,7,1])
temp = array.argsort()
ranks = numpy.arange(len(array))[temp.argsort()]
Gibt es bessere / schnellere Methoden, die es vermeiden, das Array zweimal zu sortieren?
ranks = temp.argsort()
.Antworten:
Verwenden Sie im letzten Schritt das Schneiden auf der linken Seite:
Dadurch wird vermieden, dass zweimal sortiert wird, indem die Permutation im letzten Schritt invertiert wird.
quelle
Verwenden Sie argsort zweimal, um zuerst die Reihenfolge des Arrays zu ermitteln und dann die Rangfolge zu ermitteln:
Stellen Sie beim Umgang mit 2D-Arrays (oder höherdimensionalen Arrays) sicher, dass Sie ein Achsenargument an argsort übergeben, um es über die richtige Achse zu ordnen.
quelle
[4,2,7,1,1]
), die Ausgabe diese Zahlen basierend auf ihrer Array-Position ([3,2,4,0,1]
)argsort
.array = np.random.rand(10)
sollte seinarray = np.random.rand(n)
.Diese Frage ist ein paar Jahre alt und die akzeptierte Antwort ist großartig, aber ich denke, das Folgende ist immer noch erwähnenswert. Wenn Ihnen die Abhängigkeit nichts ausmacht
scipy
, können Sie Folgendes verwendenscipy.stats.rankdata
:Ein nettes Merkmal von
rankdata
ist, dass dasmethod
Argument mehrere Optionen für den Umgang mit Bindungen bietet. Zum Beispiel gibt es drei Vorkommen von 20 und zwei Vorkommen von 40 inb
:Die Standardeinstellung weist den gebundenen Werten den Durchschnittsrang zu:
method='ordinal'
weist aufeinanderfolgende Ränge zu:method='min'
weist allen gebundenen Werten den Mindestrang der gebundenen Werte zu:Weitere Optionen finden Sie in der Dokumentzeichenfolge.
quelle
rankdata
derselbe Mechanismus wie die akzeptierte Antwort verwendet wird, um das anfängliche Ranking intern zu generieren.Ich habe versucht, beide Lösungen für Arrays A mit mehr als einer Dimension zu erweitern, vorausgesetzt, Sie verarbeiten Ihr Array zeilenweise (Achse = 1).
Ich habe den ersten Code mit einer Schleife für Zeilen erweitert. wahrscheinlich kann es verbessert werden
Und der zweite, der dem Vorschlag von k.rooijers folgt, wird:
Ich habe zufällig 400 Arrays mit Form (1000.100) generiert. Der erste Code dauerte ungefähr 7,5, der zweite 3,8.
quelle
Eine vektorisierte Version eines gemittelten Ranges finden Sie unten. Ich liebe np.unique, es erweitert wirklich den Umfang dessen, was Code effizient vektorisiert werden kann und was nicht. Abgesehen von der Vermeidung von Python-for-Schleifen vermeidet dieser Ansatz auch die implizite Doppelschleife über 'a'.
quelle
Neben der Eleganz und Kürze der Lösungen stellt sich auch die Frage nach der Leistung. Hier ist ein kleiner Maßstab:
quelle
rankdata(l, method='ordinal') - 1
.Verwenden Sie argsort () zweimal, um dies zu tun:
quelle
Ich habe die oben genannten Methoden ausprobiert, bin aber gescheitert, weil ich viele Zeoren hatte. Ja, auch bei Floats können doppelte Elemente wichtig sein.
Also schrieb ich eine modifizierte 1D-Lösung, indem ich einen Schritt zur Überprüfung der Krawatte hinzufügte:
Ich glaube, es ist so effizient wie es nur sein kann.
quelle
Ich mochte die Methode von k.rooijers, aber wie rcoup schrieb, werden wiederholte Zahlen nach der Array-Position eingestuft. Das war nicht gut für mich, deshalb habe ich die Version geändert, um die Ränge nachzubearbeiten und alle wiederholten Zahlen zu einem kombinierten Durchschnittsrang zusammenzuführen:
Ich hoffe, das könnte auch anderen helfen. Ich habe versucht, eine andere Lösung dafür zu finden, konnte aber keine finden ...
quelle
Argsort und Slice sind Symmetrieoperationen.
Versuchen Sie es zweimal mit Slice anstatt zweimal mit Argsort. da Slice schneller ist als Argsort
quelle
Allgemeinere Version einer der Antworten:
Siehe Verwenden von numpy.argsort () als Indizes in mehr als zwei Dimensionen. auf mehr Dims verallgemeinern.
quelle