wake-up-neo.net

Arrays in NumPy nach Spalte sortieren

Wie kann ich ein Array in NumPy nach der n-ten Spalte sortieren?

Zum Beispiel,

a = array([[9, 2, 3],
           [4, 5, 6],
           [7, 0, 5]])

Ich möchte die Zeilen nach der zweiten Spalte sortieren, sodass ich zurückkomme:

array([[7, 0, 5],
       [9, 2, 3],
       [4, 5, 6]])
242
user248237dfsf

@steve 's ist eigentlich die eleganteste Art und Weise, dies zu tun.

Für den "richtigen" Weg sehen Sie das Argument für die Reihenfolge von numpy.ndarray.sort

Sie müssen Ihr Array jedoch als Array mit Feldern (strukturiertes Array) anzeigen.

Der "richtige" Weg ist ziemlich hässlich, wenn Sie Ihr Array anfangs nicht mit Feldern definiert haben ...

Um es kurz zu sortieren und eine Kopie zurückzugeben:

In [1]: import numpy as np

In [2]: a = np.array([[1,2,3],[4,5,6],[0,0,1]])

In [3]: np.sort(a.view('i8,i8,i8'), order=['f1'], axis=0).view(np.int)
Out[3]: 
array([[0, 0, 1],
       [1, 2, 3],
       [4, 5, 6]])

Um es vor Ort zu sortieren:

In [6]: a.view('i8,i8,i8').sort(order=['f1'], axis=0) #<-- returns None

In [7]: a
Out[7]: 
array([[0, 0, 1],
       [1, 2, 3],
       [4, 5, 6]])

@ Steve's ist wirklich der eleganteste Weg, so weit ich weiß ... 

Der einzige Vorteil dieser Methode besteht darin, dass das Argument "Reihenfolge" eine Liste der Felder ist, nach denen die Suche sortiert werden soll. Sie können beispielsweise nach der zweiten Spalte, dann nach der dritten Spalte und dann nach der ersten Spalte sortieren, indem Sie order = ['f1', 'f2', 'f0'] angeben.

104
Joe Kington

Ich nehme an, das funktioniert: a[a[:,1].argsort()]

Dies zeigt die zweite Spalte von a an und sortiert sie entsprechend.

551
Steve Tjoa

Sie können nach Steve Tjoas Methode nach mehreren Spalten sortieren, indem Sie eine stabile Sortierung wie Mergesort verwenden und die Indizes von den niedrigstwertigen zu den höchstwertigen Spalten sortieren:

a = a[a[:,2].argsort()] # First sort doesn't need to be stable.
a = a[a[:,1].argsort(kind='mergesort')]
a = a[a[:,0].argsort(kind='mergesort')]

Dies wird nach Spalte 0, dann 1 und 2 sortiert.

22
J.J

Aus dem Python-Dokumentations-Wiki , ich denke, Sie können Folgendes tun:

a = ([[1, 2, 3], [4, 5, 6], [0, 0, 1]]); 
a = sorted(a, key=lambda a_entry: a_entry[1]) 
print a

Die Ausgabe ist:

[[[0, 0, 1], [1, 2, 3], [4, 5, 6]]]
17
user541064

Von der NumPy-Mailingliste , hier eine andere Lösung:

>>> a
array([[1, 2],
       [0, 0],
       [1, 0],
       [0, 2],
       [2, 1],
       [1, 0],
       [1, 0],
       [0, 0],
       [1, 0],
      [2, 2]])
>>> a[np.lexsort(np.fliplr(a).T)]
array([[0, 0],
       [0, 0],
       [0, 2],
       [1, 0],
       [1, 0],
       [1, 0],
       [1, 0],
       [1, 2],
       [2, 1],
       [2, 2]])
14
fgregg

Für den Fall, dass jemand die Sortierung in einem kritischen Teil ihrer Programme verwenden möchte, folgt ein Leistungsvergleich für die verschiedenen Vorschläge:

import numpy as np
table = np.random.Rand(5000, 10)

%timeit table.view('f8,f8,f8,f8,f8,f8,f8,f8,f8,f8').sort(order=['f9'], axis=0)
1000 loops, best of 3: 1.88 ms per loop

%timeit table[table[:,9].argsort()]
10000 loops, best of 3: 180 µs per loop

import pandas as pd
df = pd.DataFrame(table)
%timeit df.sort_values(9, ascending=True)
1000 loops, best of 3: 400 µs per loop

Es sieht also so aus, als wäre die Indexierung mit argsort die bisher schnellste Methode ...

13
MonkeyButter

Ich hatte ein ähnliches Problem.

Mein Problem:

Ich möchte eine SVD berechnen und muss meine Eigenwerte in absteigender Reihenfolge sortieren. Ich möchte aber die Abbildung zwischen Eigenwerten und Eigenvektoren beibehalten. Meine Eigenwerte waren in der ersten Zeile und der entsprechende Eigenvektor in derselben Spalte.

Ich möchte also ein zweidimensionales Array spaltenweise nach der ersten Zeile in absteigender Reihenfolge sortieren.

Meine Lösung

a = a[::, a[0,].argsort()[::-1]]

Wie funktioniert das?

a[0,] ist nur die erste Zeile, nach der ich sortieren möchte.

Jetzt benutze ich argsort, um die Reihenfolge der Indizes zu ermitteln.

Ich benutze [::-1], weil ich eine absteigende Reihenfolge brauche.

Schließlich benutze ich a[::, ...], um eine Ansicht mit den Spalten in der richtigen Reihenfolge zu erhalten.

3
xuma202

Ein etwas komplizierteres lexsort-Beispiel - absteigend in der 1. Spalte, sekundär aufsteigend in der 2. Spalte. Die Tricks mit lexsort sind so, dass sie nach Zeilen sortiert werden (daher der .T) und der letzten Priorität geben.

In [120]: b=np.array([[1,2,1],[3,1,2],[1,1,3],[2,3,4],[3,2,5],[2,1,6]])
In [121]: b
Out[121]: 
array([[1, 2, 1],
       [3, 1, 2],
       [1, 1, 3],
       [2, 3, 4],
       [3, 2, 5],
       [2, 1, 6]])
In [122]: b[np.lexsort(([1,-1]*b[:,[1,0]]).T)]
Out[122]: 
array([[3, 1, 2],
       [3, 2, 5],
       [2, 1, 6],
       [2, 3, 4],
       [1, 1, 3],
       [1, 2, 1]])
1
hpaulj

Hier ist eine andere Lösung, die alle Spalten berücksichtigt (kompaktere Art der Antwort von J.J );

ar=np.array([[0, 0, 0, 1],
             [1, 0, 1, 0],
             [0, 1, 0, 0],
             [1, 0, 0, 1],
             [0, 0, 1, 0],
             [1, 1, 0, 0]])

Sortiere mit lexsort,

ar[np.lexsort(([ar[:, i] for i in range(ar.shape[1]-1, -1, -1)]))]

Ausgabe:

array([[0, 0, 0, 1],
       [0, 0, 1, 0],
       [0, 1, 0, 0],
       [1, 0, 0, 1],
       [1, 0, 1, 0],
       [1, 1, 0, 0]])
0
Sefa