Home > Software engineering >  Is there a right-left (foldr) reduction in NumPy?
Is there a right-left (foldr) reduction in NumPy?

Time:01-11

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.

  • Related