Is there a right-left (foldr) reduction in NumPy?

Question:

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?

Asked By: xpqz

||

Answers:

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.

Answered By: Jérôme Richard
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.