wake-up-neo.com

Wie kann ich parallele Numpy-Arrays "zip-sortieren"?

Wenn ich zwei parallele Listen habe und diese nach der Reihenfolge der Elemente in der ersten sortieren möchte, ist das ganz einfach:

>>> a = [2, 3, 1]
>>> b = [4, 6, 2]
>>> a, b = Zip(*sorted(Zip(a,b)))
>>> print a
(1, 2, 3)
>>> print b
(2, 4, 6)

Wie kann ich mit Numpy-Arrays dasselbe tun, ohne sie in herkömmliche Python-Listen zu entpacken?

36
YGA

b[a.argsort()] sollte den Trick machen.

So funktioniert das. Zuerst müssen Sie eine Permutation finden, die a sortiert. argsort ist eine Methode, die dies berechnet:

>>> a = numpy.array([2, 3, 1])
>>> p = a.argsort()
>>> p
[2, 0, 1]

Sie können leicht überprüfen, ob dies richtig ist:

>>> a[p]
array([1, 2, 3])

Wenden Sie jetzt dieselbe Permutation auf b an.

>>> b = numpy.array([4, 6, 2])
>>> b[p]
array([2, 4, 6])
48
Jason Orendorff

Hier ist ein Ansatz, bei dem keine Python-Zwischenlisten erstellt werden, obwohl für die Sortierung ein NumPy-Datensatzarray erforderlich ist. Wenn Ihre beiden Eingabearrays tatsächlich in Beziehung stehen (wie Spalten in einer Tabelle), kann dies eine vorteilhafte Möglichkeit für den Umgang mit Ihren Daten im Allgemeinen eröffnen, anstatt immer zwei unterschiedliche Arrays beizubehalten. In diesem Fall hätten Sie dies bereits getan Ein Datensatz-Array und Ihr ursprüngliches Problem werden nur durch Aufrufen von sort () in Ihrem Array beantwortet.

Dies führt eine In-Place-Sortierung durch, nachdem beide Arrays in ein Datensatz-Array gepackt wurden:

>>> from numpy import array, rec
>>> a = array([2, 3, 1])
>>> b = array([4, 6, 2])
>>> c = rec.fromarrays([a, b])
>>> c.sort()
>>> c.f1   # fromarrays adds field names beginning with f0 automatically
array([2, 4, 6])

Bearbeitet um rec.fromarrays () der Einfachheit halber zu verwenden, redundanten dtype zu überspringen, Standard-Sortierschlüssel zu verwenden, Standard-Feldnamen zu verwenden, anstatt (basierend auf dieses Beispiel ) anzugeben.

20
Peter Hansen

Dies ist möglicherweise der einfachste und allgemeinste Weg, um das zu tun, was Sie wollen. (Ich habe hier drei Arrays verwendet, aber dies funktioniert bei Arrays jeder Form, ob zwei Spalten oder zweihundert).

import numpy as NP
fnx = lambda : NP.random.randint(0, 10, 6)
a, b, c = fnx(), fnx(), fnx()
abc = NP.column_stack((a, b, c))
keys = (abc[:,0], abc[:,1])          # sort on 2nd column, resolve ties using 1st col
indices = NP.lexsort(keys)        # create index array
ab_sorted = NP.take(abc, indices, axis=0)

Eine Besonderheit besteht darin, dass Sie die Schlüssel in umgekehrter Reihenfolge angeben müssen, d. H. Ihren Primärschlüssel an zweiter Stelle und Ihren Sekundärschlüssel an erster Stelle setzen müssen. In meinem Beispiel möchte ich mit der 2. Spalte als Primärschlüssel sortieren, damit ich sie als zweite auflisten kann. Die erste Spalte löst nur Unentschieden auf, wird jedoch zuerst aufgeführt.

2
doug

Wie bei der Antwort von @Peter Hansen wird eine Kopie der Arrays erstellt, bevor sie sortiert werden. Aber es ist einfach, führt die Hauptsortierung durch, verwendet das zweite Array für die Hilfssortierung und sollte sehr schnell sein:

a = np.array([2, 3, 1])
b = np.array([4, 6, 2])
# combine, sort and break apart
a, b = np.sort(np.array([a, b]))
0
Matthias Fripp