3
votes

(This question is similar to Numpy averaging with multi-dimensional weights along an axis, but more complicated.)

I have a numpy array, d, d.shape=(16,3,90,144), and a numpy array of weights, e, e.shape=(16,3). I want to take a weighted average of a along axis 1 using e. So the output should be a numpy array with shape (16,90,144). I can accomplish this with a list comprehension:

np.array([np.average(d[n], weights=e[n], axis=0) for n in range(16)])

But as in the previous question, I would like to avoid having to convert from a list back to a numpy array. This case is more complicated than the previous question because the weights aren't the same each time (i.e. weights=e[n], not weights=b).

Can anybody help? Thanks!

1

1 Answers

7
votes

It would be nice to use np.average directly. However, to do so, d and the weights e would have to have the same shape, and broadcasting is not done implicitly for you here.

Explicitly broadcasting e (using np.broadcast_arrays) so it has same shape as d is possible, but a waste of memory. So instead of doing that, would could a peek at the source code defining numpy.average and try to reproduce the calculation:

In [121]: d = np.random.random((16,3,90,144))

In [122]: e = np.random.random((16,3))

In [123]: f = e[:,:,None,None]

In [124]: scl = f.sum(axis = 1)

In [125]: avg = np.multiply(d,f).sum(axis = 1)/scl

Here is a check that the calculation returns the same result as the list comprehension:

In [126]: avg_lc = np.array([np.average(d[n], weights=e[n], axis=0) for n in range(d.shape[0])])

In [127]: np.allclose(avg, avg_lc)
Out[127]: True