How to find the sum of every 4 elements in an array

Viewed 348

I have an array that will print a 10x10 random numbers from 1 to 9. I want to sum every 4 elements horizontally and vertically.

Here is the code:

import numpy as np

random_array = np.random.randint(1, 10, size=(10, 10))
print(random_array)

For example:

[[7 4 5 7 3 9 4 2 5 3]
 [2 3 7 1 1 1 4 3 2 8]
 [8 2 6 8 8 1 7 8 8 3]
 [4 7 8 8 9 5 9 2 9 7]
 [2 1 9 2 4 5 4 6 5 2]
 [3 3 1 6 4 4 7 9 7 9]
 [2 8 3 2 7 8 7 3 9 2]
 [4 4 6 5 4 1 7 5 1 1]
 [9 5 8 1 9 9 9 1 1 4]
 [8 8 6 1 3 6 4 1 8 3]] 

What I want to do is add every 4 elements horizontally and vertically. E.g. horizontally a sum of (7, 4, 5, 7) and then the sum of (4, 5, 7, 3) and so on. Then vertically the sum of(7,2,8,4) and sum of (2,8,4,2) and so on.

2 Answers

You can use slicing and np.sum

>>> a = np.random.randint(1,10, size=(10,10))
>>> a
array([[2, 5, 5, 6, 2, 7, 4, 4, 2, 7],
       [1, 4, 4, 5, 7, 1, 3, 4, 3, 5],
       [7, 8, 3, 4, 9, 7, 2, 9, 6, 8],
       [8, 8, 2, 7, 4, 3, 4, 2, 5, 6],
       [9, 7, 3, 1, 8, 4, 8, 6, 4, 3],
       [7, 9, 1, 6, 9, 9, 1, 6, 7, 5],
       [7, 6, 6, 7, 1, 4, 3, 5, 1, 9],
       [5, 4, 4, 2, 3, 8, 9, 2, 7, 2],
       [8, 2, 4, 2, 2, 8, 6, 9, 6, 7],
       [9, 4, 6, 3, 4, 2, 1, 1, 5, 2]])

>>> for i in range(4,11): 
...     print(a[0,i-4:i]) #horizontal
...
[2 5 5 6]
[5 5 6 2]
[5 6 2 7]
[6 2 7 4]
[2 7 4 4]
[7 4 4 2]
[4 4 2 7]

>>> for i in range(4,11):
...     print(a[i-4:i,0]) # vertical
...
[2 1 7 8]
[1 7 8 9]
[7 8 9 7]
[8 9 7 7]
[9 7 7 5]
[7 7 5 8]
[7 5 8 9]

## summing horizontally

>>> for i in range(4,11):
...     s+= np.sum(a[0,i-4:i])
...
>>> s
126

I would do this with convolution using np.convolve — it will be faster than looping, and I think it's more elegant than fiddling about with slices.

import numpy as np

np.random.seed(42)  # For reproducibility.
random_array = np.random.randint(1, 10, size=(10,10))

kernel = np.ones((1, 4))  # <-- 'Template' to sum a group of this shape.

# Horizontal sums.
sum_h = convolve2d(random_array, kernel, mode='valid')
print(sum_h)

This produces:

[[24. 24. 23. 22. 25. 23. 24.]
 [25. 22. 16. 21. 21. 18. 21.]
 [17. 19. 20. 15. 23. 23. 21.]
 [24. 28. 23. 22. 22. 17. 24.]
 [18. 21. 22. 19. 16. 10. 15.]
 [18. 18. 22. 18. 14. 14. 16.]
 [29. 24. 20. 20. 24. 31. 27.]
 [33. 25. 26. 25. 20. 20. 20.]
 [12. 16. 22. 28. 32. 33. 26.]
 [23. 27. 23. 24. 22. 20. 18.]]

For vertical sums you would transpose the kernel so that it's a column of ones:

convolve2d(random_array, kernel.T, mode='valid')

Specifying mode='valid' ensures that you only get the convolution result where the template fits completely over the input matrix.

Related