Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating cumulative minimum with numpy arrays

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.

like image 592
I.P. Freeley Avatar asked May 13 '14 03:05

I.P. Freeley


2 Answers

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])
like image 104
user2357112 supports Monica Avatar answered Sep 28 '22 08:09

user2357112 supports Monica


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.])
like image 30
koffein Avatar answered Sep 28 '22 08:09

koffein