2013-10-30 37 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