Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to evaluate the sum of values within array blocks

Tags:

python

numpy

I have data array, with shape 100x100. I want to divide it into 5x5 blocks, and each block has 20x20 grids. The value of each block I want is the sum of all values in it.

Is there a more elegant way to accomplish it?

x = np.arange(100)
y = np.arange(100)
X, Y = np.meshgrid(x, y)
Z = np.cos(X)*np.sin(Y)
Z_new = np.zeros((5, 5))
for i in range(5):
  for j in range(5):
    Z_new[i, j] = np.sum(Z[i*20:20+i*20, j*20:20+j*20])

This is based on index, how if based on x?

x = np.linspace(0, 1, 100)
y = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, y)
Z = np.cos(X)*np.sin(Y)
x_new = np.linspace(0, 1, 15)
y_new = np.linspace(0, 1, 15)

Z_new?

like image 448
Aristotle0 Avatar asked Apr 03 '16 08:04

Aristotle0


People also ask

How do you sum part of an array in Python?

STEP 1: Declare and initialize an array. STEP 2: The variable sum will be used to calculate the sum of the elements. Initialize it to 0. STEP 3: Loop through the array and add each element of the array to the variable sum as sum = sum + arr[i].

How do you find the sum of an array in NumPy?

sum() in Python. numpy. sum(arr, axis, dtype, out) : This function returns the sum of array elements over the specified axis.

What do you get if you apply NumPy sum () to a list that contains only Boolean values?

sum receives an array of booleans as its argument, it'll sum each element (count True as 1 and False as 0) and return the outcome. for instance np. sum([True, True, False]) will output 2 :) Hope this helps.


1 Answers

Simply reshape splitting each of those two axes into two each with shape (5,20) to form a 4D array and then sum reduce along the axes having the lengths 20, like so -

Z_new = Z.reshape(5,20,5,20).sum(axis=(1,3))

Functionally the same, but potentially faster option with np.einsum -

Z_new = np.einsum('ijkl->ik',Z.reshape(5,20,5,20))

Generic block size

Extending to a generic case -

H,W = 5,5 # block-size
m,n = Z.shape
Z_new = Z.reshape(H,m//H,W,n//W).sum(axis=(1,3))

With einsum that becomes -

Z_new = np.einsum('ijkl->ik',Z.reshape(H,m//H,W,n//W))

To compute average/mean across blocks, use mean instead of sum method.

Generic block size and reduction operation

Extending to use reduction operations that have ufuncs supporting multiple axes parameter with axis for reductions, it would be -

def blockwise_reduction(a, height, width, reduction_func=np.sum):
    m,n = a.shape
    a4D = a.reshape(height,m//height,width,n//width)
    return reduction_func(a4D,axis=(1,3))

Thus, to solve our specific case, it would be :

blockwise_reduction(Z, height=5, width=5)

and for a block-wise average computation, it would be -

blockwise_reduction(Z, height=5, width=5, reduction_func=np.mean)
like image 61
Divakar Avatar answered Nov 14 '22 23:11

Divakar