Home > Back-end >  Inconsistent manual computing of cumsumming a array in Python
Inconsistent manual computing of cumsumming a array in Python

Time:06-15

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?

CodePudding user response:

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]])

CodePudding user response:

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)
  • Related