18

I'd like to calculate the "cumulative minimum" array--basically, the minimum value of an array up to each index such as:

import numpy as np
nums = np.array([5.,3.,4.,2.,1.,1.,2.,0.])
cumulative_min = np.zeros(nums.size, dtype=float)
for i,num in enumerate(nums):
    cumulative_min[i] = np.min(nums[0:i+1])

This works (it returns the correct array([ 5., 3., 3., 2., 1., 1., 1., 0.]) ), but I'd like to avoid the for loop if I can. I thought it might be faster to construct a 2-d array and use the np.amin() function, but I needed a loop for that as well.

2 Answers 2

47

For any 2-argument NumPy universal function, its accumulate method is the cumulative version of that function. Thus, numpy.minimum.accumulate is what you're looking for:

>>> numpy.minimum.accumulate([5,4,6,10,3])
array([5, 4, 4, 4, 3])
Sign up to request clarification or add additional context in comments.

1 Comment

Cool design! NumPy's documentation gives a full list of ufuncs, including maximum, fmin, and fmax.
1

Create a matrix which lower triangle (np.tril) is filled with values of your array nums and your upper triangle (np.triu, with second parameter 1, so the diagonal stays free) is filled with the maximum of the array. (EDIT: instead of the maximum, the first element of the array is the better way. -> comments)

nums = np.array([5.,3.,4.,2.,1.,1.,2.,0.])
oneSquare = np.ones((nums.size, nums.size))

A = nums * np.tril(oneSquare)
B = np.triu(oneSquare, 1) * nums[0]
A, B

Out:

(array([[ 5.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 5.,  3.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 5.,  3.,  4.,  0.,  0.,  0.,  0.,  0.],
       [ 5.,  3.,  4.,  2.,  0.,  0.,  0.,  0.],
       [ 5.,  3.,  4.,  2.,  1.,  0.,  0.,  0.],
       [ 5.,  3.,  4.,  2.,  1.,  1.,  0.,  0.],
       [ 5.,  3.,  4.,  2.,  1.,  1.,  2.,  0.],
       [ 5.,  3.,  4.,  2.,  1.,  1.,  2.,  0.]]),
 array([[ 0.,  5.,  5.,  5.,  5.,  5.,  5.,  5.],
       [ 0.,  0.,  5.,  5.,  5.,  5.,  5.,  5.],
       [ 0.,  0.,  0.,  5.,  5.,  5.,  5.,  5.],
       [ 0.,  0.,  0.,  0.,  5.,  5.,  5.,  5.],
       [ 0.,  0.,  0.,  0.,  0.,  5.,  5.,  5.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  5.,  5.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  5.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]]))

Now take the minimum of each row:

(A+B).min(axis=1)

Out:

array([ 5.,  3.,  3.,  2.,  1.,  1.,  1.,  0.])

5 Comments

You could also use infinity for the values in the upper triangle, rather than nums.max().
@Blckknght Tried it, did not work at first glance, so I took the maximum... I tried again and infinity would change the 0-part of B to NaN
nice. Didn't know about the triangle functions, very useful.
Ah, you're right. I didn't think of 0*inf being an issue, but it is. You could use nums[0], since that's always a potential minimum value already. And really, using max wasn't too bad (it only adds an O(N)` term onto an already O(N^2) algorithm.
@Blckknght nums[0] is a good idea... I am going to change that.. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.