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])
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)
Simply reshape
splitting each of those two axes into two each with shape (5,20)
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))
Runtime test 
In [18]: x = np.arange(100)
...: y = np.arange(100)
...: X, Y = np.meshgrid(x, y)
...: Z = np.cos(X)*np.sin(Y)
...:
In [19]: %timeit Z.reshape(5,20,5,20).sum(axis=(1,3))
10000 loops, best of 3: 49.5 µs per loop
In [20]: %timeit np.einsum('ijkl>ik',Z.reshape(5,20,5,20))
10000 loops, best of 3: 46.7 µs per loop