【问题标题】:sorting numpy structured and record arrays is very slow对 numpy 结构化和记录数组进行排序非常慢
【发布时间】:2013-11-10 01:01:05
【问题描述】:

看起来,按单列对 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 创建索引数组然后使用它对各个数组重新排序可能会更快。这没关系,除了我希望处理非常大的数组并希望尽可能避免复制数据。有没有我想念的更有效的方法来做到这一点?

【问题讨论】:

    标签: python arrays sorting numpy


    【解决方案1】:

    让你变慢的是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
    

    【讨论】:

    • 啊哈!我认为 np.argsort() 在引擎盖下的顺序,但我猜不是?
    • 但实际上,这并不能解决复制数据的问题——它需要我传递 argsort 返回的索引,这将导致复制。
    【解决方案2】:

    正如 Jaime 所说,您可以使用 argsort 对记录数组进行排序。

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

    并使用take 避免复制

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

    【讨论】:

    • 唯一有效的原因是因为np.take 会在您指定out 参数并将mode 保留为默认'raise' 状态时进行复制,您可以查看at the source .如果您使用另一个mode,则不会有副本,但输出将是垃圾,一些值重复了几次,而另一些则完全丢失。
    猜你喜欢
    • 2015-02-23
    • 1970-01-01
    • 2015-11-30
    • 2013-12-21
    • 2016-11-29
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多