Search code examples
pythonnumpydeque

Computing weighted average on a deque using numpy


I have a deque object whose weighted average I would like to find. The deque object is a collection of (60 * 60 * 3) NumPy arrays (They are actually images stored in deque object). I would like to find the weighted average of all the elements(i.e images) in the deque object.

motion_buffer = deque(maxlen = 5)
motion_weights = [5./15, 4./15, 3./15, 2./15, 1./15]
# After adding few elements ( i.e images ) in motion_buffer. the following is done:
motion_avg = np.average(motion_buffer, weights=motion_weights)

I get the error:
    "Axis must be specified when shapes of a and weights "
    TypeError: Axis must be specified when shapes of a and weights differ.

I understand there is a mismatch somewhere but supplying axis values ( as per docs) did not help me. I have tested it in the following manner:

>>> A = np.random.randn(4,4)
>>> weights = [1 , 4 ,6 ,7]
>>> buf = deque(maxlen=5)
>>> buf.appendleft(A)
>>> c = np.average(buf, weights=weights)
Traceback (most recent call last):
    ...  
    "Axis must be specified when shapes of a and weights "
TypeError: Axis must be specified when shapes of a and weights differ.

I have tried using np.average for deque object with 1d elements and it works. How exactly should I modify my code, I experimented but it didn't work for me.


Solution

  • According to np.average documentation

    weights : array_like, optional
        An array of weights associated with the values in a. Each value in
        a contributes to the average according to its associated weight.
        The weights array can either be 1-D (in which case its length must be
        the size of a along the given axis) or of the same shape as a.

    you can't.

    You can implement a workaround

    av_average  = np.average(np.average(your_deque, axis=(1,2,3)), weights=(5,4,3,2,1))
    

    where you first (the inner average) mediate each 60×60×3matrix specifying the axis on which to sum and later using the weights to compute the weighted average of the averages.


    The OP really wants this

    average = np.average(the_deque, axis=0, weights=(…))
    

    where (…) is a sequence whose length equals the current length of the deque.