Sortowanie tablic w NumPy według kolumn

Jak mogę posortować tablicę w NumPy według n-tej kolumny?

Na przykład,

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

Chciałbym sortować wiersze po drugiej kolumnie, tak, że wrócę:

array([[7, 0, 5],
       [9, 2, 3],
       [4, 5, 6]])
Author: Paul Wintz, 2010-05-13

14 answers

@steve'S answer jest właściwie najbardziej eleganckim sposobem na zrobienie tego.

Aby uzyskać "poprawny" sposób zobacz argument słowa kluczowego order numpy.ndarray.Sortuj

Musisz jednak wyświetlić tablicę jako tablicę z polami (tablica strukturalna).

"poprawny" sposób jest dość brzydki, jeśli początkowo nie zdefiniowano tablicy z polami...

Jako szybki przykład, aby go posortować i zwrócić kopię:

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]])

Do sortowania in-place:

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 naprawdę jest najbardziej eleganckim sposobem, aby to zrobić, o ile wiem...

Jedyną zaletą tej metody jest to, że argument "order"jest listą pól, według których można uporządkować wyszukiwanie. Na przykład możesz sortować według drugiej kolumny, następnie trzeciej kolumny, a następnie pierwszej kolumny, podając order=['f1', 'f2', 'f0'].

 156
Author: Joe Kington,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-16 00:22:50

To chyba działa: a[a[:,1].argsort()]

Oznacza to drugą kolumnę a i odpowiednio ją posortować.

 819
Author: Steve Tjoa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-10 10:17:01

Możesz sortować na wielu kolumnach zgodnie z metodą Steve ' a Tjoa, używając stabilnego sortowania, takiego jak mergesort i sortując indeksy od najmniej znaczących do najbardziej znaczących kolumn:

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')]

Sortuje według kolumny 0, potem 1, Potem 2.

 36
Author: J.J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-25 22:37:00

Z wiki dokumentacji Pythona , myślę, że możesz to zrobić:

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

Wyjście To:

[[[0, 0, 1], [1, 2, 3], [4, 5, 6]]]
 21
Author: user541064,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 10:00:05

Jeśli ktoś chce skorzystać z sortowania w krytycznej części swoich programów, oto porównanie wydajności dla różnych propozycji:

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

Wygląda więc na to, że indeksowanie za pomocą argsort jest jak dotąd najszybszą metodą...

 20
Author: prl900,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-25 10:37:19

Z listy dyskusyjnej NumPy , oto inne rozwiązanie:

>>> 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]])
 18
Author: fgregg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 10:00:55

Miałem podobny problem.

Mój Problem:

Chcę obliczyć SVD i muszę posortować moje wartości własne W porządku malejącym. Ale chcę zachować mapowanie między wartościami własnymi i wektorami własnymi. Moje wartości własne były w pierwszym wierszu, a odpowiadający im wektor wewnętrzny pod nim w tej samej kolumnie.

Chcę więc posortować dwuwymiarową tablicę kolumn według pierwszego wiersza w porządku malejącym.

Moje Rozwiązanie

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

Więc jak czy to działa?

a[0,] to tylko pierwszy rząd, który chcę sortować według.

Teraz używam argsort aby uzyskać kolejność indeksów.

Używam [::-1] ponieważ potrzebuję malejącej kolejności.

Na koniec używam a[::, ...], aby uzyskać widok z kolumnami w odpowiedniej kolejności.

 5
Author: xuma202,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 10:09:52
import numpy as np
a=np.array([[21,20,19,18,17],[16,15,14,13,12],[11,10,9,8,7],[6,5,4,3,2]])
y=np.argsort(a[:,2],kind='mergesort')# a[:,2]=[19,14,9,4]
a=a[y]
print(a)

Pożądane wyjście to [[6,5,4,3,2],[11,10,9,8,7],[16,15,14,13,12],[21,20,19,18,17]]

Zauważ, że argsort(numArray) zwraca indeksy numArray tak, jak miało to być uporządkowane.

Przykład

x=np.array([8,1,5]) 
z=np.argsort(x) #[1,3,0] are the **indices of the predicted sorted array**
print(x[z]) #boolean indexing which sorts the array on basis of indices saved in z

Odpowiedź brzmi [1,5,8]

 3
Author: ckaus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-27 09:14:07

Przykład - malejący na pierwszej kolumnie, wtórnie rosnący na drugiej. Triki z lexsort polegają na tym, że sortuje on wiersze (stąd .T) i nadaje pierwszeństwo ostatniemu.

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
Author: hpaulj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-07 16:33:59

Oto inne rozwiązanie uwzględniające wszystkie kolumny (bardziej zwarty sposób odpowiedzi 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]])

Sortuj za pomocą lexsort,

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

Wyjście:

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
Author: Sefa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-30 19:36:58

Po prostu używając sortowania, użyj numeru coloumn na podstawie którego chcesz sortować.

a = np.array([1,1], [1,-1], [-1,1], [-1,-1]])
print (a)
a=a.tolist() 
a = np.array(sorted(a, key=lambda a_entry: a_entry[0]))
print (a)
 0
Author: Jerin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-19 17:13:49

Jest to stare pytanie, ale jeśli trzeba uogólnić to do macierzy wyższych niż 2, Oto rozwiązanie, które można łatwo uogólnić:

np.einsum('ij->ij', a[a[:,1].argsort(),:])

Jest to przesada dla dwóch wymiarów i a[a[:,1].argsort()] wystarczyłoby na odpowiedź @steve ' a, jednak ta odpowiedź nie może być uogólniona na wyższe wymiary. Możesz znaleźć przykład tablicy 3D w tym pytaniu.

Wyjście:

[[7 0 5]
 [9 2 3]
 [4 5 6]]
 0
Author: Ehsan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-27 04:59:01

#do sortowania wzdłuż kolumny 1

indexofsort=np.argsort(dataset[:,0],axis=-1,kind='stable') 
dataset   = dataset[indexofsort,:]
 0
Author: umair ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-15 08:45:00
def sort_np_array(x, column=None, flip=False):
    x = x[np.argsort(x[:, column])]
    if flip:
        x = np.flip(x, axis=0)
    return x

Tablica w pytaniu pierwotnym:

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

Wynik funkcji sort_np_array zgodnie z oczekiwaniami autora pytania:

sort_np_array(a, column=1, flip=False)
[2]: array([[7, 0, 5],
            [9, 2, 3],
            [4, 5, 6]])
 0
Author: Arkady,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-31 14:58:57