2017-01-05 4 views
1

Numpyで2つ以上の属性のオブジェクトの配列を効率的に並べ替えるにはどうすればよいですか?numpyでオブジェクトの配列をソートしますか?

class Obj(): 
    def __init__(self,a,b): 
     self.a = a 
     self.b = b 

arr = np.array([],dtype=Obj)   

for i in range(10): 
    arr = np.append(arr,Obj(i, 10-i)) 

arr_sort = np.sort(arr, order=a,b) ??? 

Thxを、ウィレム月

+0

numpyはデータ型のクラスをサポートしていますか? 'np.array([]、dtype = Obj)'? –

+0

オブジェクト配列ではなくリストを使用します。リストの追加が高速です。リストソートではキーパラメータのソートが可能です。 – hpaulj

+0

多分あなたは[構造化配列](https://docs.scipy.org/doc/numpy/user/basics.rec.html)を探しています。彼らはPythonクラスで直接動作しません。 – user7138814

答えて

0

orderパラメータは、構造のアレイに適用される:lexsortは同様のソート

In [402]: arr=np.column_stack((np.arange(10),10-np.arange(10))) 
In [403]: np.lexsort((arr[:,1],arr[:,0])) 
Out[403]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32) 
In [404]: np.lexsort((arr[:,0],arr[:,1])) 
Out[404]: array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0], dtype=int32) 
'順序付け' 提供し、2Dアレイと

In [383]: arr=np.zeros((10,),dtype='i,i') 
In [385]: for i in range(10): 
    ...:  arr[i] = (i,10-i) 
In [386]: arr 
Out[386]: 
array([(0, 10), (1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3), (8, 2), (9, 1)], 
     dtype=[('f0', '<i4'), ('f1', '<i4')]) 
In [387]: np.sort(arr, order=['f0','f1']) 
Out[387]: 
array([(0, 10), (1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3), (8, 2), (9, 1)], 
     dtype=[('f0', '<i4'), ('f1', '<i4')]) 
In [388]: np.sort(arr, order=['f1','f0']) 
Out[388]: 
array([(9, 1), (8, 2), (7, 3), (6, 4), (5, 5), (4, 6), (3, 7), (2, 8), 
     (1, 9), (0, 10)], 
     dtype=[('f0', '<i4'), ('f1', '<i4')]) 

オブジェクト配列を使用して、attこれらの構造のいずれかにributes:

In [407]: np.array([(a.a, a.b) for a in arr]) 
Out[407]: 
array([[ 0, 10], 
     [ 1, 9], 
     [ 2, 8], 
     .... 
     [ 7, 3], 
     [ 8, 2], 
     [ 9, 1]]) 
In [408]: np.array([(a.a, a.b) for a in arr],dtype='i,i') 
Out[408]: 
array([(0, 10), (1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3), 
     (8, 2), (9, 1)], 
     dtype=[('f0', '<i4'), ('f1', '<i4')]) 

ザ・パイソンsorted機能が

In [421]: arr 
Out[421]: 
array([<__main__.Obj object at 0xb0f2d24c>, 
     <__main__.Obj object at 0xb0f2dc0c>, 
     .... 
     <__main__.Obj object at 0xb0f35ecc>], dtype=object) 
In [422]: sorted(arr, key=lambda a: (a.b,a.a)) 
Out[422]: 
[<__main__.Obj at 0xb0f35ecc>, 
<__main__.Obj at 0xb0f3570c>, 
... 
<__main__.Obj at 0xb0f2dc0c>, 
<__main__.Obj at 0xb0f2d24c>] 

あなたObjクラスが素敵__str__方法が欠落しているarr(またはそのリストに相当)で動作します。 arr要素の値を見るには、[(i.a, i.b) for i in arr]のようなものを使用しなければなりません。

コメントに記載されているように、この例では、リストはオブジェクト配列よりも優れています。

In [423]: alist=[] 
In [424]: for i in range(10): 
    ...:  alist.append(Obj(i,10-i)) 

リストappendは、繰り返し配列の追加よりも高速です。また、オブジェクト配列はリストに比べて多くの機能を追加しません(特に1dの場合)。オブジェクトはこのようなカスタムクラスです。 arrで数学を行うことはできません。ご覧のとおり、並べ替えはそれほど簡単ではありません。

関連する問題