繁体   English   中英

python & numpy:数组切片的总和

[英]python & numpy: sum of an array slice

我有一维 numpy 数组( array_ )和一个 Python 列表(list_)。

以下代码有效,但效率低下,因为切片涉及不必要的副本(当然对于 Python 列表,我相信也适用于 numpy arrays?):

result = sum(array_[1:])
result = sum(list_[1:])

重写它的好方法是什么?

切片 numpy 数组不会像在列表的情况下那样进行复制。

作为一个基本示例:

import numpy as np
x = np.arange(100)
y = x[1:5]
y[:] = 1000
print x[:10]

这产生:

[   0 1000 1000 1000 1000    5    6    7    8    9]

尽管我们修改了y中的值,但这只是对与x相同的 memory 的视图。

切片 ndarray 会返回一个视图并且不会复制 memory。

但是,使用array_[1:].sum()而不是在 numpy 数组上调用 python 的内置sum会更有效。

作为一个快速比较:

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

编辑:

在列表的情况下,如果由于某种原因您不想制作副本,您可以随时使用itertools.islice 代替:

result = sum(some_list[1:])

你可以这样做:

result = sum(itertools.islice(some_list, 1, None))

不过,在大多数情况下,这太过分了。 如果您处理的列表足够长以至于 memory 管理是一个主要问题,那么您可能不应该使用列表来存储您的值。 (列表并非旨在或旨在将项目紧凑地存储在 memory 中。)

此外,您不希望对 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

我尝试了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

此外,在更大的数字上,它的速度要慢得多!

>>> setup = setup.replace("range(1000)", "range(1000000)")
>>> timeit.timeit("custom_sum(l, 50, 950000)", setup, number=10)
14.185815095901489

我想不出还有什么可以测试的。 (想法,有人吗?)

@Joe Kington(这是仅显示我的时间安排的临时答案,我会尽快将其删除):

In []: x= arange(1e4)
In []: %timeit sum(x)
100000 loops, best of 3: 18.8 us per loop
In []: %timeit x.sum()
100000 loops, best of 3: 17.5 us per loop
In []: x= arange(1e5)
In []: %timeit sum(x)
10000 loops, best of 3: 165 us per loop
In []: %timeit x.sum()
10000 loops, best of 3: 158 us per loop
In []: x= arange(1e2)
In []: %timeit sum(x)
100000 loops, best of 3: 4.44 us per loop
In []: %timeit x.sum()
100000 loops, best of 3: 3.2 us per loop

据我的 numpy(1.5.1) 消息来源所说, sum(.)只是x.sum(.)的包装器。 因此,对于sum(.)x.sum(.) ,对于较大的输入,执行时间相同(渐近)。

编辑:这个答案只是一个临时答案,但实际上它(及其评论)可能确实对某人有用。 所以我就让它保持原样,直到有人真的要求我删除它。

我没有发现x[1:].sum()明显慢于x.sum() 对于列表sum(x) - x[0]sum(x[1:])快(OMM 快大约 40%)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM