python - فرز المصفوفات في NumPy حسب العمود




arrays sorting (6)

أفترض أن هذا يعمل: a[a[:,1].argsort()]

كيف يمكنني فرز مصفوفة في NumPy بواسطة العمود nth؟

فمثلا،

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

أريد فرز الصفوف في العمود الثاني ، بحيث أعود:

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

في حالة ما إذا أراد شخص ما الاستفادة من الفرز في جزء هام من برامجه ، فإليك مقارنة الأداء مع المقترحات المختلفة:

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

لذلك ، يبدو أن الفهرسة مع argsort هي أسرع طريقة حتى الآن ...


مثال lexsort أكثر تعقيدًا lexsort - نزولاً على العمود الأول ، تصاعديًا في الثاني. الحيل مع lexsort هي أنه lexsort على الصفوف (ومن ثم .T lexsort ) ، ويعطي الأولوية لآخر.

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

من القائمة البريدية لـ NumPy ، إليك الحل الآخر:

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

هنا هو حل آخر النظر في جميع الأعمدة (طريقة أكثر لإجابة ) ؛

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

فرز مع lexsort ،

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

انتاج:

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

يمكنك الفرز على أعمدة متعددة وفقًا لطريقة Steve Tjoa باستخدام تصنيف ثابت مثل mergesort وفرز المؤشرات من الأقل أهمية إلى الأعمدة الأكثر أهمية:

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

هذا الفرز حسب العمود 0 ، ثم 1 ، ثم 2.





scipy