max*_*max 9 python arrays numpy
我有一维numpy数组(array_)和一个Python列表(list_).
以下代码有效,但效率低,因为切片涉及不必要的副本(当然对于Python列表,我也相信numpy数组?):
result = sum(array_[1:])
result = sum(list_[1:])
Run Code Online (Sandbox Code Playgroud)
什么是改写它的好方法?
Joe*_*ton 13
切片numpy数组不会复制,就像列表一样.
作为一个基本的例子:
import numpy as np
x = np.arange(100)
y = x[1:5]
y[:] = 1000
print x[:10]
Run Code Online (Sandbox Code Playgroud)
这会产生:
[ 0 1000 1000 1000 1000 5 6 7 8 9]
Run Code Online (Sandbox Code Playgroud)
即使我们修改了值y,它只是对同一个内存的视图x.
切片ndarray会返回一个视图,并且不会复制内存.
但是,使用array_[1:].sum()而不是sum在numpy数组上调用python的内置函数会更有效.
作为快速比较:
In [28]: x = np.arange(10000)
In [29]: %timeit x.sum()
100000 loops, best of 3: 10.2 us per loop
In [30]: %timeit sum(x)
100 loops, best of 3: 4.01 ms per loop
Run Code Online (Sandbox Code Playgroud)
编辑:
在列表的情况下,如果由于某种原因您不想复制,您可以随时使用itertools.islice.代替:
result = sum(some_list[1:])
Run Code Online (Sandbox Code Playgroud)
你可以这样做:
result = sum(itertools.islice(some_list, 1, None))
Run Code Online (Sandbox Code Playgroud)
但在大多数情况下,这是过度杀伤.如果您处理列表的时间足够长,以至于内存管理是一个主要问题,那么您可能不应该使用列表来存储您的值.(列表不是为了将内容紧凑地存储在内存中而设计的.)
此外,您不希望为numpy数组执行此操作.简单地做some_array[1:].sum()会更快级的几个订单,并不会使用任何比更多的内存islice.
当我谈到列表时,我的第一直觉就像Joe Kington一样,但我检查过,至少在我的机器上,islice它一直都很慢!
>>> timeit.timeit("sum(l[50:950])", "l = range(1000)", number=10000)
1.0398731231689453
>>> timeit.timeit("sum(islice(l, 50, 950))", "from itertools import islice; l = range(1000)", number=10000)
1.2317550182342529
>>> timeit.timeit("sum(l[50:950000])", "l = range(1000000)", number=10)
7.9020509719848633
>>> timeit.timeit("sum(islice(l, 50, 950000))", "from itertools import islice; l = range(1000000)", number=10)
8.4522969722747803
Run Code Online (Sandbox Code Playgroud)
我试了一下custom_sum,发现它更快,但不是很多:
>>> setup = """
... def custom_sum(list, start, stop):
... s = 0
... for i in xrange(start, stop):
... s += list[i]
... return s
...
... l = range(1000)
... """
>>> timeit.timeit("custom_sum(l, 50, 950)", setup, number=1000)
0.66767406463623047
Run Code Online (Sandbox Code Playgroud)
此外,在更大的数字,它到目前为止更慢!
>>> setup = setup.replace("range(1000)", "range(1000000)")
>>> timeit.timeit("custom_sum(l, 50, 950000)", setup, number=10)
14.185815095901489
Run Code Online (Sandbox Code Playgroud)
我想不出别的东西要测试.(想,有人吗?)
| 归档时间: |
|
| 查看次数: |
26734 次 |
| 最近记录: |