# [Numpy-discussion] Reductions with nditer working only with the last axis

Sergio Pascual sergiopr at fis.ucm.es
Mon Oct 1 18:01:05 EDT 2012

```Perhaps sum wasn't the best function for this example. I'm going to
rework the code with other function

Consider a function that operates on an array and returns a number

def myfunc(data):
return data.min() + 2 * data.max()

The function with nditer is:

def nditer_fun(data, axes):
it = numpy.nditer([data, None],
flags=['reduce_ok', 'external_loop'],
op_axes=[None, axes])
it.operands[1][...] = 0

for x, y in it:
y[...] = myfun(x)

return it.operands[1]

We can compara the result of this function with the result of
numpy.apply_along_axis
With the data

data = numpy.arange(2*3*4).reshape((2,3,4))

the values obtained with axis 0 ara

numpy.apply_along_axis(myfun, 0 ,data)
[[24 27 30 33]
[36 39 42 45]
[48 51 54 57]]

nditer_fun(data, [-1, 0, 1])
[[58 58 58 58]
[58 58 58 58]
[58 58 58 58]]

Only along the last axis both functions give the same result

2012/10/1 Han Genuit <hangenuit at gmail.com>:
> On Thu, Sep 27, 2012 at 6:08 PM, Sergio Pascual <sergio.pasra at gmail.com> wrote:
>> Hello, I'm trying to understand how to work with nditer to do a
>> reduction, in my case converting a 3d array into a 2d array.
>>
>> I followed the help here
>> http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html and
>> managed to create a function that applies reduction over the last axis
>> of the input. With this function
>>
>> def nditer_sum(data, red_axes):
>>     it = numpy.nditer([data, None],
>>                 flags=['reduce_ok', 'external_loop'],
>>                 op_axes=[None, red_axes])
>>     it.operands[1][...] = 0
>>
>>     for x, y in it:
>>         y[...] = x.sum()
>>
>>     return it.operands[1]
>>
>> I can get something equivalent to data.sum(axis=2)
>>
>>>>> data = numpy.arange(2*3*4).reshape((2,3,4))
>>>>> nditer_sum(data, [0, 1, -1])
>> [[ 6 22 38]
>>  [54 70 86]]
>>>>> data.sum(axis=2)
>> [[ 6 22 38]
>>  [54 70 86]]
>>
>> So to get something equivalent to data.sum(axis=0) I though that it
>> was enough to change  the argument red_axes to [-1, 0,1]
>> But the result is quite different.
>>
>>>>> data = numpy.arange(2*3*4).reshape((2,3,4))
>>>>> data.sum(axis=0)
>> [[12 14 16 18]
>>  [20 22 24 26]
>>  [28 30 32 34]]
>>>>> nditer_sum(data, [-1, 0, 1])
>> [[210 210 210 210]
>>  [210 210 210 210]
>>  [210 210 210 210]]
>>
>> In the for loop inside nditer_sum (for x,y in it:), the iterator is
>> looping 2 times and giving an array of length 12 each time, instead of
>> looping 12 times and giving an array of length 2 each time. I have
>> no avail.
>>
>> Does anybody have an example of a reduction in the first axis of an
>> array using nditer? Is this a bug?
>>
>>
>> Regards, Sergio
>> _______________________________________________
>> NumPy-Discussion mailing list
>> NumPy-Discussion at scipy.org
>> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
> The example from the link it shows how to do a reduction with y[...]
> += x. If you would replace x.sum() by += x, then it works.
>
>>>> nditer_sum(data, [-1,0,1])
> array([[12, 14, 16, 18],
>        [20, 22, 24, 26],
>        [28, 30, 32, 34]])
>>>> data.sum(axis=0)
> array([[12, 14, 16, 18],
>        [20, 22, 24, 26],
>        [28, 30, 32, 34]])
>
>>>> nditer_sum(data, [0,-1,1])
> array([[12, 15, 18, 21],
>        [48, 51, 54, 57]])
>>>> data.sum(axis=1)
> array([[12, 15, 18, 21],
>        [48, 51, 54, 57]])
>
> I think that is because sum() already reduces all axis by default.
>
> Regards,
> Han
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion

--
Sergio Pascual     http://guaix.fis.ucm.es/~spr    +34 91 394 5018
gpg fingerprint: 5203 B42D 86A0 5649 410A F4AC A35F D465 F263 BCCC