2012-04-19 14 views
5

Tengo una lista de números de coma flotante y quiero generar otra lista de declaraciones de períodos de mi primera lista.¿Cuál es la forma más pitónica de calcular los cambios porcentuales en una lista de números?

Este es un negocio de la aplicación del molino (no probado - y, obviamente, sin comprobación de errores/manipulación):

a = [100,105,100,95,100] 

def calc_period_returns(values, period): 
    output = [] 
    startpos, endpos = (period, len(values)-1) 

    while True: 
     current = values[startpos] 
     previous = values[startpos-period] 
     ret = 100*((current-previous)/(1.0*previous)) 
     output.append(ret) 
     startpos += period 
     if startpos > endpos: 
      break 
    return output 


calc_period_returns(a,1) 

# Expected output: 
# [5.0, -4.7619047619047619, -5.0, 5.2631578947368416] 

¿Hay una manera más Pythonic de hacer esto - tal vez utilizando la lista de comprensión y mapas?

+1

¿cuál es la salida deseada? –

+0

@RomanBodnarchuk: He actualizado la pregunta con un resultado esperado –

+0

ver la actualización de la respuesta. –

Respuesta

10

Aquí van:

>>> [100.0 * a1/a2 - 100 for a1, a2 in zip(a[1:], a)] 
[5.0, -4.7619047619047592, -5.0, 5.2631578947368354] 

Dado que se desea comparar los elementos vecinos de una lista, es mejor crear una lista de pares le interesa, como esto:

>>> a = range(5) 
>>> a 
[0, 1, 2, 3, 4] 
>>> zip(a, a[1:]) 
[(0, 1), (1, 2), (2, 3), (3, 4)] 

Después de eso es solo una matemática simple extraer un cambio porcentual de un par de números.

+0

¿Conocía esta Terminología o descifró su código? – Abhijit

+0

@Abhijit levemente :) Simplemente entrada mapeada a la salida :) –

+0

Sólo un pequeño FYI, esto falla con la división por cero si alguno de los números es cero. – mikkom

15

No sé qué tan grande será su lista de números, pero si va a procesar grandes cantidades de números, debería echar un vistazo a numpy. El efecto secundario es que los cálculos parecen mucho más simples.

Con numpy, se crea una matriz de datos

>>> import numpy as np 
>>> a = np.array([100,105,100,95,100], dtype=float) 

y trabajar con matrices como si fueran simples números

>>> np.diff(a)/a[:-1] * 100. 
[ 5.   -4.76190476 -5.   5.26315789] 
+1

En realidad, lo que realmente quieres es 'np.diff (a)/np.abs (a [: - 1]) * 100'. Además, un elemento en a podría ser 0, por lo que para evitar dividir entre 0 error, puede hacer algo como 'a [a == 0] = 0.000000001' –

Cuestiones relacionadas