Cómo aplicar una función a cada elemento de una matriz cuando el resultado depende de la celda anterior

Tengo una matriz:

a = np.array([2,3,5,8,3,5]) 

¿Cuál es la forma más eficiente (vectorizada) de calcular una matriz donde cada elemento resultante es (Pseudocódigo):

 result[0] = a[0] for i > 0: result[i] = result[i-1] + (a[i] - result[i-1]) * factor 

Podría hacer esto con el siguiente código ineficiente (factor = 0.5):

 a = np.array([2,3,5,8,3,5]) result = np.array([a[0]]) for k in a[1:]: result = np.append(result, result[-1]+(k-result[-1])*0.5) 

El resultado de esta función de amortiguación sería:

 array([ 2., 2.5, 3.75, 5.875, 4.4375, 4.71875]) 

Está buscando la alternativa de scanl1 de Haskell en Python (ejemplo de Haskell):

 Prelude> scanl1 (\ab -> a + (b - a) * 0.5) [2, 3, 5, 8, 3, 5] [2.0,2.5,3.75,5.875,4.4375,4.71875] 

Hay una función de accumulate en el módulo itertools :

 In [1]: import itertools In [2]: itertools.accumulate([2, 3, 5, 8, 3, 5], lambda a, b: a + (b - a) * 0.5) Out[2]:  In [3]: list(itertools.accumulate([2, 3, 5, 8, 3, 5], lambda a, b: a + (b - a) * 0.5)) Out[3]: [2, 2.5, 3.75, 5.875, 4.4375, 4.71875] 

Con NumPy puede usar la función numpy.ufunc.accumulate , sin embargo, de acuerdo con esta respuesta , hay un error en la implementación, es por eso que deberíamos usar una conversión. Desafortunadamente, no estoy muy familiarizado con NumPy y, probablemente, hay una mejor manera:

 In [9]: import numpy as np In [10]: uf = np.frompyfunc(lambda a, b: a + (b - a) * 0.5, 2, 1) In [11]: uf.accumulate([2,3,5,8,3,5], dtype=np.object).astype(np.float) Out[11]: array([ 2. , 2.5 , 3.75 , 5.875 , 4.4375 , 4.71875]) 

Me gustaría publicar cómo funciona el código @soon, o cómo implementarlo con reduce :

 def scanl(f, v): return reduce(lambda (l, v1), v:(l+[f(v1, v)], f(v1, v)), v[1:], ([v[0]], v[0]))[0] >>> scanl(lambda a, b: a + (b - a) * 0.5,[2, 3, 5, 8, 3, 5]) [2, 2.5, 3.75, 5.875, 4.4375, 4.71875] 

No es el mejor rendimiento ni el más bonito, pero te da una idea de cómo hacerlo.