average numpy array but retain shape

2019-06-16 18:51发布

问题:

I have a Numpy 3 axis array whose elements are 3 dimensional. I'd like to average them and return the same shape of the array. The normal average function removes the 3 dimensions and replace it with the average (as expected):

a = np.array([[[0.1, 0.2, 0.3], [0.2, 0.3, 0.4]],
              [[0.4, 0.4, 0.4], [0.7, 0.6, 0.8]]], np.float32)

b = np.average(a, axis=2)
# b = [[0.2, 0.3],
#      [0.4, 0.7]]

Result required:

# b = [[[0.2, 0.2, 0.2], [0.3, 0.3, 0.3]],
#      [[0.4, 0.4, 0.4], [0.7, 0.7, 0.7]]]

Can you do this elegantly or do I just have to iterate over the array in Python (which will be a lot slower compared to a powerful Numpy function).

Can you set the Dtype argument, for the np.mean function, to a 1D array perhaps?

Thanks.

回答1:

>>> import numpy as np
>>> a = np.array([[[0.1, 0.2, 0.3], [0.2, 0.3, 0.4]],
...               [[0.4, 0.4, 0.4], [0.7, 0.6, 0.8]]], np.float32)
>>> b = np.average(a, axis=2)
>>> b
array([[ 0.2       ,  0.29999998],
       [ 0.40000001,  0.69999999]], dtype=float32)
>>> c = np.dstack((b, b, b))
>>> c
array([[[ 0.2       ,  0.2       ,  0.2       ],
        [ 0.29999998,  0.29999998,  0.29999998]],

       [[ 0.40000001,  0.40000001,  0.40000001],
        [ 0.69999999,  0.69999999,  0.69999999]]], dtype=float32)


回答2:

Ok, CAUTION I don't have my masters in numpyology yet, but just playing around, I came up with:

>>> np.average(a,axis=-1).repeat(a.shape[-1]).reshape(a.shape)
array([[[ 0.2       ,  0.2       ,  0.2       ],
        [ 0.29999998,  0.29999998,  0.29999998]],

       [[ 0.40000001,  0.40000001,  0.40000001],
        [ 0.69999999,  0.69999999,  0.69999999]]], dtype=float32)


回答3:

Have you considered using broadcasting? Here is more info about broadcasting if you're new to the concept.

Here is an example using broadcast_arrays, keep in mind that the b produced here by broadcast_arrays should be treated as read only, you should make a copy if you want to write to it:

>>> b = np.average(a, axis=2)[:, :, np.newaxis]
>>> b, _ = np.broadcast_arrays(b, a)
>>> b
array([[[ 0.2       ,  0.2       ,  0.2       ],
        [ 0.29999998,  0.29999998,  0.29999998]],

       [[ 0.40000001,  0.40000001,  0.40000001],
        [ 0.69999999,  0.69999999,  0.69999999]]], dtype=float32)


回答4:

Here is a method that avoids making copies:

a = a.T
a[:] = a.mean(axis=0)
a = a.T

Or if you don't want to overwrite a:

b = np.empty_like(a)
b = b.T
b[:] = a.mean(axis=-1).T
b = b.T


回答5:

This is for an arbitrary axis:

array is the ndimentional array and axis is the axis to average

np.repeat( np.expand_dims( np.mean( array, axis ), axis ), array.shape[axis], axis )