我正在寻找一种用 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])
与累积:
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)
最佳答案
如果计算出循环的结果,请从序列 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
则可能是 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])
但总的来说,我担心您将不得不保留循环。
关于python - "np.cumsum() like"- 根据实际值迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15466287/