May-18-2018, 08:47 PM
What you are looking for is a moving average. I use normally variations of this answer in stackoverflow
when I have to deal with that type of arrays I prefer this version:
def moving_avg(a, n): # Notice that in the original here forces dtype=float... # I prefer to keep dtype of a, as not always work with float acc = np.cumsum(a) acc[n:] = acc[n:] - acc[:-n] return acc[n-1:] / nNotice that this is fast but can be problematic when the array has many elements or outliers and the accumulated sum is too big and produces a degradation in the accuracy of the result.
when I have to deal with that type of arrays I prefer this version:
def ha_moving_avg(a, n): sz = len(a) - n + 1 # acc = a[:sz].copy() acc = 0 for k in range(n): acc += a[k:sz+k] return acc / nIs slower, but if your data has big values or can contain outliers you can have disgusting surprises... consider the following:
def demo(): n = 3 # Just to print nice the arrays fmt = {'all': lambda x: '%.1g' % x} print("Nice inputs") # Let's try something nice... # m[k] = k so the average of 3 elements is: # (k + k+1 + k+2) / 3 = k + 1 m = np.arange(10) ma = moving_avg(m, n) print("\tNormal: " + np.array2string(ma, formatter=fmt)) ma = ha_moving_avg(m, n) print("\tHigh Acc: " + np.array2string(ma, formatter=fmt)) print("Broken Inputs") m = np.ones(10) m[4] = 1E20 ma = moving_avg(m, n) print("\tNormal: " + np.array2string(ma, formatter=fmt)) ma = ha_moving_avg(m, n) print("\tHigh Acc: " + np.array2string(ma, formatter=fmt)) if __name__ == '__main__': demo()
Output:Nice inputs
Normal: [1 2 3 4 5 6 7 8]
High Acc: [1 2 3 4 5 6 7 8]
Broken Inputs
Normal: [1 1 3e+19 3e+19 3e+19 0 0 0]
High Acc: [1 1 3e+19 3e+19 3e+19 1 1 1]
See the surprise?