Reputation: 843
I'm searching a way to implement with numpy this piece of python code:
N = np.arange(5)
for i in range(5):
for k in range(i):
N[i] += N[k]
Assuming that I work in fact on big 2-D arrays (1300*1300).
np.cumsum()
provide a good way, on one axis N[0][i]
or N[i][0]
, except that it only sums the values of the original array, not of the evolving array.
I can't figure a way to do that. Any Idea ?
@Edit :
To make things clear :
With 1-D array the loop give
Out[89]: array([ 0, 1, 3, 7, 15])
With cumsum :
array([ 0, 1, 3, 6, 10])
With a 2-D, it would give something like :
N = np.arange(25).reshape(5,5)
for i in range(len(N)):
N = np.cumsum(N, axis=i)
Upvotes: 1
Views: 395
Reputation: 67457
If you work out the result of your loop, starting with a sequence a[n]
, and what comes out of the two for loops is a sequence b[n]
, then:
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]
where I am defining:
c[n-1] = a[n-1] + 2*a[n-2] + 4*a[n-3] + ... + 2**(n-2)*a[0]
With this last expression in mind, there are ways to vectorize your double loop. But note the very large factors(2**(n-2)
) by which you have to multiply the items in your sequence. If your sequence has positive and negative terms, these may cancel out and return reasonable numbers. But if you have an array of over 1000 positive elements, then you are going to overflow any numpy dtype.
So for short sequences of less than 30 items, perhaps 60 if you force using int64
's, the following will work faster than your for loops:
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])
But in general I am afraid you are going to have to keep your loops.
Upvotes: 2
Reputation: 3624
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]
What do you mean by evolving array?
Upvotes: 0