NumPy's .reduce()
is a foldl
, reducing left to right:
>>> np.subtract.reduce(np.array([1, 2, 3]))
-4
So (1-2)-3
. Is there a standard numpy way of doing foldr
instead (right to left), that is to get 1-(2-3)
in this simple case?
CodePudding user response:
AFAIK, there are no right-to-left reduction in Numpy: all reduction are performed from the left to the right. When the binary operator is associative, the foldl approach is analytically equivalent to foldr (it can be numerically different up using floating-point numbers but changing the ordering that way is generally not useful expect in very-rare cases like exponentially decreasing sorted numbers). In the specific case of np.subtract.reduce
, there is no need for a foldr approach. Indeed:
a_1 - (a_2 - (a_3 - (a_4 - (a_5 - (... - a_n)))))
= a_1 - a_2 a_3 - a_4 a_5 - ... -/ a_n
= (a_1 a_3 a_5 ... a_i) - (a_2 a_4 a_6 ... a_j)
This means one can use:
result = np.add.reduce(arr[::2]) - np.add.reduce(arr[1::2])
There is no need for foldr reduction to be implemented in Numpy. A general way to perform a folr reduction is to write a user-defined function reduction:
f = np.frompyfunc(lambda x,y: y-x, 2, 1)
result = f.reduce(arr[::-1])
The downside of this method is that it is not very fast because of the CPython function being interpreted and called every time from the native C Numpy code.
Alternatively, you can write your own foldr reduction method using Numba so to get a fast implementation.