1

我正在寻找一种用 numpy 实现这段 python 代码的方法:

  N = np.arange(5)

  for i in range(5):
     for k in range(i):
        N[i] += N[k]

假设我实际上在大型二维数组 (1300*1300) 上工作。

np.cumsum()提供一个好方法,在一个轴N[0][i]或上N[i][0],除了它只对原始数组的值求和,而不是对进化数组的值求和。

我想不出办法做到这一点。任何想法 ?

@编辑 :

为了清楚起见:

使用一维数组,循环给出

Out[89]: array([ 0,  1,  3,  7, 15])

与 cumsum :

array([ 0,  1,  3,  6, 10])

使用二维,它会给出类似的东西:

N = np.arange(25).reshape(5,5)
for i in range(len(N)):
    N = np.cumsum(N, axis=i)
4

2 回答 2

2

如果你计算出循环的结果,从一个序列开始a[n],两个 for 循环的结果是一个序列b[n],那么:

b[n] = a[n] + a[n-1] + 2*a[n-2] + 4*a[n-3] + ... + 2**(n-2)*a[0] =
       a[n] + c[n-1] 

我在哪里定义:

c[n-1] = a[n-1] + 2*a[n-2] + 4*a[n-3] + ... + 2**(n-2)*a[0]

记住最后一个表达式,有一些方法可以矢量化你的双循环。但是请注意非常大的因数(2**(n-2)),您必须乘以您的序列中的项目。如果您的序列有正数和负数,它们可能会抵消并返回合理的数字。但是如果你有一个超过 1000 个正元素的数组,那么你将溢出任何 numpy dtype。

因此,对于少于 30 个项目的短序列,如果您强制使用int64's 可能是 60 个,以下将比您的 for 循环更快地工作:

def evolving_cumsum(arr):
    arr = np.array(arr) # makes a copy of the data
    pows = 2**np.arange(len(arr))[::-1]
    c = np.cumsum(arr*pows)
    c /= pows
    arr[1:] += c[:-1]
    return arr

>>> a = np.arange(10)
>>> evolving_cumsum(a)
array([  0,   1,   3,   7,  15,  31,  63, 127, 255, 511])
>>> for i in range(len(a)):
...     for k in range(i):
...         a[i] += a[k]
... 
>>> a
array([  0,   1,   3,   7,  15,  31,  63, 127, 255, 511])

但总的来说,我担心你将不得不保持你的循环。

于 2013-03-18T01:51:58.400 回答
0
import numpy as np
N = np.arange(5)
print np.cumsum(N) # outputs [ 0  1  3  6 10]

for i in range(5):
    for k in range(i):
        N[i] += N[k]

print np.cumsum(N) # outputs [ 0  1  4 11 26]

进化数组是什么意思?

于 2013-03-17T22:37:39.700 回答