2014-05-13 38 views
8

mi piacerebbe per calcolare la matrice "minima cumulativa" - in pratica, il valore minimo di un array fino a ciascun indice, quali:Calcolo minima cumulativa con array NumPy

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]) 

Questo funziona (restituisce la matrice corretta ([5., 3., 3., 2., 1., 1., 1., 0.]) ), ma mi piacerebbe evitare il ciclo for se possibile. Ho pensato che potrebbe essere più veloce costruire un array 2-d e usare la funzione np.amin(), ma avevo anche bisogno di un loop per quello.

risposta

16

Per qualsiasi NumPy a 2 argomenti universal function, il suo metodo accumulate è la versione cumulativa di tale funzione. Così, numpy.minimum.accumulate è quello che stai cercando:

>>> numpy.minimum.accumulate([5,4,6,10,3]) 
array([5, 4, 4, 4, 3]) 
1

Creare una matrice che triangolo inferiore (np.tril) è riempito con valori dell'array nums e proprio triangolo superiore (np.triu, con 1 secondo parametro, così libere le diagonali) è riempito con il massimo della matrice. (EDIT:. Invece del massimo, il primo elemento della matrice è il modo migliore -> commenti)

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.]])) 

Ora prendete il minimo di ogni riga :

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

out:

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

Si potrebbe anche usare l'infinito per i valori nel triangolo superiore, piuttosto che 'nums.max()'. – Blckknght

+0

@Blckknght Provato, non ha funzionato a prima vista, quindi ho preso il massimo ... Ho provato di nuovo e infinity cambierebbe la parte '0' di' B' in 'NaN' – koffein

+0

nice. Non conoscevo le funzioni del triangolo, molto utile. –