tiempo movil machine learning graficar con python numpy scipy time-series

movil - series de tiempo con python



¿Cómo calcular el promedio móvil usando NumPy? (2)

Parece que no hay una función que simplemente calcule el promedio móvil en numpy / scipy, lo que lleva a soluciones intrincadas .

Mi pregunta es doble:

  • ¿Cuál es la forma más fácil de (correctamente) implementar una media móvil con numpy?
  • Dado que esto parece no trivial y propenso a errores, ¿hay una buena razón para no tener las baterías incluidas en este caso?

La falta de NumPy de una función específica de dominio particular tal vez se deba a la disciplina y fidelidad del equipo central a la directiva principal de NumPy: proporcionar un tipo de matriz N-dimensional , así como funciones para crear e indexar esas matrices. Al igual que muchos objetivos fundamentales, este no es pequeño, y NumPy lo hace brillantemente.

El (mucho) más grande SciPy contiene una colección mucho más grande de bibliotecas específicas de dominio (llamadas subpaquetes por SciPy devs) - por ejemplo, optimización numérica ( optimizar ), procesamiento de señal ( señal ) y cálculo integral ( integrar ).

Supongo que la función que buscas está en al menos uno de los subpaquetes de SciPy ( scipy.signal quizás); sin embargo, buscaría primero en la colección de scikits de SciPy , identificaré los scikit (s) relevantes y buscaré la función de interés allí.

Los Scikits son paquetes desarrollados independientemente basados ​​en NumPy / SciPy y dirigidos a una disciplina técnica particular (p. Ej., Scikits-image , scikits-learn , etc.). Varios de estos fueron (en particular, el asombroso OpenOpt para la optimización numérica) muy apreciados. proyectos maduros mucho antes de elegir residir bajo la rúbrica de scikits relativamente nueva. A la página de inicio de Scikits le gustaban enumerar unos 30 de estos scikits , aunque al menos varios de ellos ya no se encuentran en desarrollo activo.

Seguir este consejo te llevaría a scikits-timeseries ; sin embargo, ese paquete ya no se encuentra en desarrollo activo; En efecto, Pandas se ha convertido, AFAIK, en la biblioteca de series de tiempo basadas en NumPy de facto .

Pandas tiene varias funciones que se pueden usar para calcular un promedio móvil ; el más simple de estos es probablemente rolling_mean , que se usa así:

>>> # the recommended syntax to import pandas >>> import pandas as PD >>> import numpy as NP >>> # prepare some fake data: >>> # the date-time indices: >>> t = PD.date_range(''1/1/2010'', ''12/31/2012'', freq=''D'') >>> # the data: >>> x = NP.arange(0, t.shape[0]) >>> # combine the data & index into a Pandas ''Series'' object >>> D = PD.Series(x, t)

Ahora, simplemente llame a la función rolling_mean pasando el objeto Serie y un tamaño de ventana , que en mi ejemplo a continuación es de 10 días .

>>> d_mva = PD.rolling_mean(D, 10) >>> # d_mva is the same size as the original Series >>> d_mva.shape (1096,) >>> # though obviously the first w values are NaN where w is the window size >>> d_mva[:3] 2010-01-01 NaN 2010-01-02 NaN 2010-01-03 NaN

verificar que funcionó - por ejemplo, valores comparados 10 - 15 en la serie original versus la nueva serie alisada con media rodante

>>> D[10:15] 2010-01-11 2.041076 2010-01-12 2.041076 2010-01-13 2.720585 2010-01-14 2.720585 2010-01-15 3.656987 Freq: D >>> d_mva[10:20] 2010-01-11 3.131125 2010-01-12 3.035232 2010-01-13 2.923144 2010-01-14 2.811055 2010-01-15 2.785824 Freq: D

La función rolling_mean, junto con aproximadamente una docena más o menos de otra función, se agrupan informalmente en la documentación de Pandas bajo las funciones de la ventana de movimiento de rúbrica; un segundo grupo relacionado de funciones en Pandas se conoce como funciones ponderadas exponencialmente (p. ej., ewma , que calcula el promedio ponderado exponencialmente en movimiento). El hecho de que este segundo grupo no esté incluido en el primero (funciones de ventana móvil ) es tal vez porque las transformaciones ponderadas exponencialmente no se basan en una ventana de longitud fija


Si solo quiere un promedio móvil directo no ponderado, puede implementarlo fácilmente con np.cumsum , que puede ser más rápido que los métodos basados ​​en FFT:

EDITAR corrigió una indexación equivocada manchada por Bean en el código. EDITAR

def moving_average(a, n=3) : ret = np.cumsum(a, dtype=float) ret[n:] = ret[n:] - ret[:-n] return ret[n - 1:] / n >>> a = np.arange(20) >>> moving_average(a) array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18.]) >>> moving_average(a, n=4) array([ 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5])

Así que supongo que la respuesta es: es realmente fácil de implementar, y tal vez numpy ya está un poco abultado con funcionalidades especializadas.