I've helped with the other apply
function more, so have had to look at the docs and experiment.
But look at what happens when we call your function:
In [185]: method_name(a,0)
Out[185]: <function __main__.method_name.<locals>.<lambda>(x)>
It returned the lambda function. apply
expects the function call to return an array, hence the complaint that it doesn't have a ndim
.
Change the function:
def method_name(x,axis=0):
l = lambda x: print(x) or x ** 2
return l(x)
Now it works:
In [187]: np.apply_over_axes(method_name, a,0)
[[0 1 2]
[3 4 5]]
Out[187]:
array([[ 0, 1, 4],
[ 9, 16, 25]])
So it has called the method_name
once, passing it a
. Your lambda prints a
(as a side effect) and returns its square.
What if we provide 2 axes values?
In [188]: np.apply_over_axes(method_name, a,[0,1])
[[0 1 2]
[3 4 5]]
[[ 0 1 4]
[ 9 16 25]]
Out[188]:
array([[ 0, 1, 16],
[ 81, 256, 625]])
It's squared it twice! For the 2nd call it passed as x
the result from the first call. The axes don't have to be unique or in order either: np.apply_over_axes(method_name, a,[0,1,0,1])
The docs illustrate it with np.sum
as the function, and demonstrate the equivalence with sum
using several axes. Originally functions like sum
took just one axis value. In that case this apply_over_axes
would have been a handy way of repeating the sum (instead of np.sum(np.sum(a, 0),0)
). But now functions like that take a list, so there's less need for this apply_over_axes
function.
cumsum
might be a better illustration than sum
, since it returns an array of the dimensions, and doesn't take multiple axes:
sum vertically:
In [210]: np.cumsum(a,0)
Out[210]:
array([[0, 1, 2],
[3, 5, 7]])
and again across columns:
In [211]: np.cumsum(_,1)
Out[211]:
array([[ 0, 1, 3],
[ 3, 8, 15]])
Doing the same thing with apply
:
In [212]: np.apply_over_axes(np.cumsum, a, [0])
Out[212]:
array([[0, 1, 2],
[3, 5, 7]])
In [213]: np.apply_over_axes(np.cumsum, a, [0,1])
Out[213]:
array([[ 0, 1, 3],
[ 3, 8, 15]])
or another:
In [229]: l = lambda a, axis: np.add.accumulate(a**2, axis)
In [230]: l(l(a,0),1)
Out[230]:
array([[ 0, 1, 17],
[ 81, 370, 1211]])
In [231]: np.apply_over_axes(l, a, [0,1])
Out[231]:
array([[ 0, 1, 17],
[ 81, 370, 1211]])
It may be more useful for a case where the function reduces the dimensions, such as a reduce
:
In [236]: rl = lambda a, axis: np.add.reduce(a**2, axis)
In [237]: np.apply_over_axes(rl, a, [0,1])
Out[237]: array([[1211]])
apply_over_axes
does an better job of keeping track of dimensions than nested calls:
In [239]: rl(rl(a,0),0)
Out[239]: 1211
In [240]: rl(rl(a,0)[None,:],1)
Out[240]: array([1211])