14

I have a large array of thousands of vals in numpy. I want to decrease its size by averaging adjacent values. For example:

a = [2,3,4,8,9,10]
#average down to 2 values here
a = [3,9]
#it averaged 2,3,4 and 8,9,10 together

So, basically, I have n number of elements in array, and I want to tell it to average down to X number of values, and it averages like above.

Is there some way to do that with numpy (already using it for other things, so I'd like to stick with it).

Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
Adam Haile
  • 30,705
  • 58
  • 191
  • 286
  • 1
    I was going to propose `reshape` and then `mean`, but that would be the same as the accepted answer to [this question](http://stackoverflow.com/questions/20322079/downsample-a-1d-numpy-array). Would that work for your purposes? – DSM Oct 29 '14 at 18:56
  • 2
    Dear Adam, I hope you found the answers given below to be helpful. Please accept one of the many answers given if you found them useful. =) – Siddharth Satpathy Nov 28 '18 at 04:25

4 Answers4

20

Using reshape and mean, you can average every m adjacent values of an 1D-array of size N*m, with N being any positive integer number. For example:

import numpy as np

m = 3
a = np.array([2, 3, 4, 8, 9, 10])
b = a.reshape(-1, m).mean(axis=1)
#array([3., 9.])

1)a.reshape(-1, m) will create a 2D image of the array without copying data:

array([[ 2,  3,  4],
       [ 8,  9, 10]])

2)taking the mean in the second axis (axis=1) will then calculate the mean value of each row, resulting in:

array([3., 9.])
Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
0

Looks like a simple non-overlapping moving window average to me, how about:

In [3]:

import numpy as np
a = np.array([2,3,4,8,9,10])
window_sz = 3
a[:len(a)/window_sz*window_sz].reshape(-1,window_sz).mean(1) 
#you want to be sure your array can be reshaped properly, so the [:len(a)/window_sz*window_sz] part
Out[3]:
array([ 3.,  9.])
CT Zhu
  • 52,648
  • 17
  • 120
  • 133
0

Try this:

n_averaged_elements = 3
averaged_array = []
a = np.array([ 2,  3,  4,  8,  9, 10])
for i in range(0, len(a), n_averaged_elements):
   slice_from_index = i
   slice_to_index = slice_from_index + n_averaged_elements
   averaged_array.append(np.mean(a[slice_from_index:slice_to_index]))

>>>> averaged_array
>>>> [3.0, 9.0]
0

In this example, I presume that a is the 1D numpy array that needs to be averaged. In the method that I give below, we first find the factors of the length of this array a. And, then we choose the an appropriate factor as the step size to average the array with.

Here is the code.

import numpy as np
from functools import reduce

''' Function to find factors of a given number 'n' '''
def factors(n):    
    return list(set(reduce(list.__add__, 
        ([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0))))

a = [2,3,4,8,9,10]  #Given array.

'''fac: list of factors of length of a. 
   In this example, len(a) = 6. So, fac = [1, 2, 3, 6] '''
fac = factors(len(a)) 

'''step: choose an appropriate step size from the list 'fac'.
   In this example, we choose one of the middle numbers in fac 
   (3). '''   
step = fac[int( len(fac)/3 )+1]

'''avg: initialize an empty array. '''
avg = np.array([])
for i in range(0, len(a), step):
    avg = np.append( avg, np.mean(a[i:i+step]) ) #append averaged values to `avg`

print avg  #Prints the final result

[3.0, 9.0]      
Siddharth Satpathy
  • 2,737
  • 4
  • 29
  • 52