2013-10-30 38 views
7

它看起來像由一個單一列排序numpy的結構和記錄陣列比類似的獨立陣列上做一個排序慢得多:排序numpy的結構和記錄陣列很慢

In [111]: a = np.random.rand(1e4) 

In [112]: b = np.random.rand(1e4) 

In [113]: rec = np.rec.fromarrays([a,b]) 

In [114]: timeit rec.argsort(order='f0') 
100 loops, best of 3: 18.8 ms per loop 

In [115]: timeit a.argsort() 
1000 loops, best of 3: 891 µs per loop 

有一個邊際改善使用結構化陣列,但它不是戲劇性:

In [120]: struct = np.empty(len(a),dtype=[('a','f8'),('b','f8')]) 

In [121]: struct['a'] = a 

In [122]: struct['b'] = b 

In [124]: timeit struct.argsort(order='a') 
100 loops, best of 3: 15.8 ms per loop 

這表明,它是潛在更快地創建從argsort索引陣列,然後使用該重新排序的單獨的陣列。除了我希望處理非常大的數組並希望儘可能避免複製數據外,這是行得通的。有沒有更有效的方法來做到這一點,我錯過了?

回答

3

由於海梅有說過,你可以用argsort來排序記錄數組。

inds = np.argsort(rec['f0']) 

並使用take避免製作副本

np.take(rec, inds, out=rec) 
+2

工作的唯一原因是因爲'np.take'在指定'out'參數時創建一個副本,並將'mode'保留爲默認的'raise'狀態,您可以查看[at the source]( https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/item_selection.c#L99)。如果您使用另一個'mode',則不會複製,但輸出將是垃圾,其中一些值會重複多次,而其他值則會完全丟失。 – Jaime

4

什麼是減慢你使用order,而不是你有一個記錄陣列的事實。如果你想通過一個單一的字段進行排序,像這樣做:

In [12]: %timeit np.argsort(rec['f0']) 
1000 loops, best of 3: 829 us per loop 

一旦order使用,性能南下無論你想有多少個字段進行排序:

In [16]: %timeit np.argsort(rec, order=['f0']) 
10 loops, best of 3: 27.9 ms per loop 

In [17]: %timeit np.argsort(rec, order=['f0', 'f1']) 
10 loops, best of 3: 28.4 ms per loop 
+0

啊哈!我認爲順序做了np.argsort(),但我猜不是嗎? – Rok

+1

但實際上,這並沒有解決複製數據的問題 - 它需要我傳遞argsort返回的索引,這會導致副本。 – Rok