12

There is a numpy way to make a sum each three elements in the interval? For example:

import numpy as np
mydata = np.array([4, 2, 3, 8, -6, 10])

I would like to get this result:

np.array([9, 13, 5, 12])
Divakar
  • 218,885
  • 19
  • 262
  • 358
marcelorodrigues
  • 919
  • 5
  • 12
  • 22

3 Answers3

27

We can use np.convolve -

np.convolve(mydata,np.ones(3,dtype=int),'valid')

The basic idea with convolution is that we have a kernel that we slide through the input array and the convolution operation sums the elements multiplied by the kernel elements as the kernel slides through. So, to solve our case for a window size of 3, we are using a kernel of three 1s generated with np.ones(3).

Sample run -

In [334]: mydata
Out[334]: array([ 4,  2,  3,  8, -6, 10])

In [335]: np.convolve(mydata,np.ones(3,dtype=int),'valid')
Out[335]: array([ 9, 13,  5, 12])
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • Ah now I understand. Based on the provided data I tried it with np.convolve(mydata,[1,2],'valid') and did not understand why the result is not [8, 8, 19, -4, 14]. But this is the output of np.convolve(mydata,[2,1],'valid'). All clear now :-) – Ohumeronen Jul 21 '16 at 15:35
9

Starting in Numpy 1.20, the sliding_window_view provides a way to slide/roll through windows of elements. Windows that you can then individually sum:

from numpy.lib.stride_tricks import sliding_window_view

# values = np.array([4, 2, 3, 8, -6, 10])
np.sum(sliding_window_view(values, window_shape = 3), axis = 1)
# array([9, 13, 5, 12])

where:

  • window_shape is the size of the sliding window
  • np.sum(array, axis = 1) sums sub-arrays

and the intermediate result of the sliding is:

sliding_window_view(np.array([4, 2, 3, 8, -6, 10]), window_shape = 3)
# array([[ 4,  2,  3],
#        [ 2,  3,  8],
#        [ 3,  8, -6],
#        [ 8, -6, 10]])
Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
2

A solution without using external libraries might look like this:

from collections import deque

def sliding_window_sum(a, size):
  out     = []
  the_sum = 0
  q       = deque()
  for i in a:
    if len(q)==size:
      the_sum -= q[0]
      q.popleft()
    q.append(i)
    the_sum += i
    if len(q)==size:
      out.append(the_sum)
  return out

v = [0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1]
sliding_window_sum(v, 5)

Which gives the output:

[1, 2, 3, 3, 4, 4, 3, 2, 3, 2, 1, 1, 1, 0, 0, 1]

This matches the result of using numpy:

import numpy as np
np.convolve(v, np.ones(5, dtype=int),'valid').tolist()
Richard
  • 56,349
  • 34
  • 180
  • 251