John Stone
John Stone

Reputation: 715

Inconsistent manual computing of cumsumming a array in Python

I know Python starts initial index of a array from 0 and I also know x[:,:k] means first k column of array x, then I try

## prepare array
x = np.array([1, -2, 0, -2, 5, 0, 0, 0, 2]).reshape(3,-1) 
x

## use cumsum
x1 = np.cumsum(x,axis=1)
x1

## manually compute
x2 = np.zeros(x.shape) 
for k in range(x.shape[1]):
  x2[:,k] = np.sum(x[:,:k],axis=1) 

x2

However, I found x1 is inconsistent with x2. Why?

Upvotes: 0

Views: 46

Answers (2)

hpaulj
hpaulj

Reputation: 231510

In [20]: x = np.array([1, -2, 0, -2, 5, 0, 0, 0, 2]).reshape(3,-1)

In [21]: x
Out[21]: 
array([[ 1, -2,  0],
       [-2,  5,  0],
       [ 0,  0,  2]])

x is symmetric, but the cumsum is not.

In [22]: np.cumsum(x,axis=1)
Out[22]: 
array([[ 1, -1, -1],
       [-2,  3,  3],
       [ 0,  0,  2]], dtype=int32)

The first column is the same as in x. The 2nd is x[:,0]+x[:,1], etc.

Change the axis, and the result is just the transpose.

In [23]: np.cumsum(x,axis=0)
Out[23]: 
array([[ 1, -2,  0],                # x[0,:]
       [-1,  3,  0],                # x[0,:]+x[1,:]
       [-1,  3,  2]], dtype=int32)

We can iterate across the columns with:

In [25]: res = np.zeros((3,3),int)
    ...: res[:,0] = x[:,0]
    ...: for i in range(1,3):
    ...:     res[:,i] = res[:,i-1] + x[:,i]
    ...:     

In [26]: res
Out[26]: 
array([[ 1, -1, -1],
       [-2,  3,  3],
       [ 0,  0,  2]])

Your iteration is has 0 in the first column, not x[:,0]:

In [27]: res = np.zeros((3,3),int)
    ...: for i in range(0,3):
    ...:     res[:,i] = x[:,:i].sum(axis=1)
    ...:     

In [28]: res
Out[28]: 
array([[ 0,  1, -1],
       [ 0, -2,  3],
       [ 0,  0,  0]])

That's because the :i does not include i.

In [29]: res = np.zeros((3,3),int)
    ...: for i in range(0,3):
    ...:     res[:,i] = x[:,:i+1].sum(axis=1)
    ...:     

In [30]: res
Out[30]: 
array([[ 1, -1, -1],
       [-2,  3,  3],
       [ 0,  0,  2]])

Upvotes: 2

Ali_Sh
Ali_Sh

Reputation: 2816

Using numpy in loops in not a recommended way, particularly when numpy have equivalent modules. But, in case of this question, you can do this as:

x2 = np.zeros(x.shape)
for k in range(x.shape[1]):
    for j in range(x.shape[0]):
        x2[k, j] = np.sum(x[k, :j+1])

or if axis=0:

x2 = np.zeros(x.shape)
for k in range(x.shape[1]):
    for j in range(x.shape[0]):
        x2[j, k] = np.sum(x[:j+1, k])

If you want to know how to modify your code, you must use k+1 instead of k in np.sum because range is starting from 0 --> :k will be :0 ==> :k+1 will be :1

x2 = np.zeros(x.shape)
for k in range(x.shape[1]):
  x2[:, k] = np.sum(x[:, :k+1], axis=1)

Upvotes: 1

Related Questions