Parece que no hay una función que simplemente calcule el promedio móvil en numpy / scipy, lo que lleva a soluciones complicadas .
Mi pregunta es doble:
python
numpy
scipy
time-series
moving-average
Goncalopp
fuente
fuente
Respuestas:
Si lo que desea es un simple no ponderado promedio móvil, se puede implementar fácilmente con
np.cumsum
, quepuede seres métodos más rápido que la FFT en base:EDITAR Se corrigió una indexación incorrecta de uno en uno detectada por Bean en el código. EDITAR
Así que supongo que la respuesta es: es realmente fácil de implementar, y tal vez numpy ya esté un poco hinchado con funcionalidad especializada.
fuente
ret[n:] -= ret[:-n]
NO ES LO MISMO queret[n:] = ret[n:] - ret[:-n]
. He arreglado el código en esta respuesta. Editar: No, alguien más se me adelantó.La falta de NumPy de una función específica de dominio particular se debe quizás a la disciplina y fidelidad del Core Team a la directiva principal de NumPy: proporcionar un tipo de matriz N-dimensional , así como funciones para crear e indexar esas matrices. Como muchos objetivos fundamentales, este no es pequeño y NumPy lo hace de manera brillante.
El SciPy (mucho) más grande contiene una colección mucho mayor de bibliotecas específicas de dominio (llamadas subpaquetes por los desarrolladores de SciPy), por ejemplo, optimización numérica ( optimizar ), procesamiento de señales ( señal ) y cálculo integral ( integrar ).
Supongo que la función que busca está en al menos uno de los subpaquetes de SciPy ( quizás scipy.signal ); sin embargo, buscaría primero en la colección de scikits de ciencia ficción , identificaría los scikit relevantes y buscaría la función de interés allí.
Scikits son paquetes desarrollados de forma independiente basados en NumPy / SciPy y dirigidos a una disciplina técnica en particular (por ejemplo, scikits-image , scikits-learn , etc.). Varios de ellos (en particular, el impresionante OpenOpt para optimización numérica) fueron muy apreciados, proyectos maduros mucho antes de elegir residir bajo la rúbrica de scikits relativamente nueva . La página de inicio de Scikits que le gustó arriba enumera alrededor de 30 de esos scikits , aunque al menos varios de ellos ya no están en desarrollo activo.
Seguir este consejo lo llevará a scikits-timeseries ; sin embargo, ese paquete ya no se encuentra en desarrollo activo; En efecto, Pandas se ha convertido, AFAIK, el de facto NumPy biblioteca de series de tiempo basada en .
Pandas tiene varias funciones que pueden usarse para calcular un promedio móvil ; el más simple de estos es probablemente rolling_mean , que usa así:
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 .
verificar que funcionó, por ejemplo, comparar los valores 10-15 en la serie original con la nueva Serie suavizada con media móvil
La función rolling_mean, junto con alrededor de una docena de otras funciones se agrupan informalmente en la documentación de Pandas bajo la rúbrica funciones de ventana móvil ; un segundo grupo de funciones relacionado en Pandas se conoce como funciones ponderadas exponencialmente (por ejemplo, ewma , que calcula el promedio ponderado móvil exponencial). El hecho de que este segundo grupo no esté incluido en el primero ( funciones de ventana móvil ) se debe quizás a que las transformaciones ponderadas exponencialmente no dependen de una ventana de longitud fija
fuente
Una forma sencilla de lograr esto es usando
np.convolve
. La idea detrás de esto es aprovechar la forma en que se calcula la convolución discreta y usarla para devolver una media móvil . Esto se puede hacer convolucionando con una secuencia denp.ones
de una longitud igual a la longitud de la ventana deslizante que queremos.Para ello podríamos definir la siguiente función:
Esta función tomará la convolución de la secuencia
x
y una secuencia de unos de longitudw
. Tenga en cuenta que lo elegidomode
esvalid
para que el producto de convolución solo se proporcione para los puntos donde las secuencias se superponen por completo.Algunos ejemplos:
Para una media móvil con una ventana de longitud
2
tendríamos:Y para una ventana de largo
4
:¿Cómo
convolve
funciona?Echemos un vistazo más en profundidad a la forma en que se calcula la convolución discreta. La siguiente función tiene como objetivo replicar la forma
np.convolve
se calculan los valores de salida:Lo cual, para el mismo ejemplo anterior, también produciría:
Entonces, lo que se está haciendo en cada paso es tomar el producto interno entre la matriz de unos y la ventana actual . En este caso la multiplicación por
np.ones(w)
es superflua dado que estamos tomando directamente lasum
de la secuencia.A continuación se muestra un ejemplo de cómo se calculan las primeras salidas para que sea un poco más claro. Supongamos que queremos una ventana de
w=4
:Y la siguiente salida se calcularía como:
Y así sucesivamente, devolviendo un promedio móvil de la secuencia una vez que se hayan realizado todas las superposiciones.
fuente
mode='valid'
se puede reemplazar con'same'
. Solo en este caso, los puntos de borde gravitarán hacia cero.Aquí hay una variedad de formas de hacer esto, junto con algunos puntos de referencia. Los mejores métodos son las versiones que utilizan código optimizado de otras bibliotecas. El
bottleneck.move_mean
método probablemente sea el mejor en todos los aspectos. Elscipy.convolve
enfoque también es muy rápido, extensible y sintácticamente y conceptualmente simple, pero no se escala bien para valores de ventana muy grandes. Elnumpy.cumsum
método es bueno si necesitas un puronumpy
enfoque .Nota: algunos de estos (p
bottleneck.move_mean
. Ej. ) No están centrados y cambiarán sus datos.Tiempo, ventana pequeña (n = 3)
Tiempo, ventana grande (n = 1001)
Memoria, ventana pequeña (n = 3)
Memoria, ventana grande (n = 1001)
fuente
Esta respuesta que usa Pandas está adaptada de arriba, ya que
rolling_mean
ya no es parte de PandasAhora, simplemente llame a la función
rolling
en el marco de datos con un tamaño de ventana, que en mi ejemplo a continuación es de 10 días.fuente
Siento que esto se puede resolver fácilmente usando el cuello de botella
Vea la muestra básica a continuación:
Esto da media de movimiento a lo largo de cada eje.
"mm" es la media móvil de "a".
"ventana" es el número máximo de entradas a considerar para la media móvil.
"min_count" es el número mínimo de entradas a considerar para la media móvil (por ejemplo, para el primer elemento o si la matriz tiene valores nan).
Lo bueno es que Bottleneck ayuda a lidiar con los valores nan y también es muy eficiente.
fuente
En caso de que desee cuidar las condiciones de los bordes con cuidado ( calcule la media solo a partir de los elementos disponibles en los bordes ), la siguiente función funcionará.
fuente
Prueba este fragmento de código. Creo que es más simple y funciona. retroceso es la ventana de la media móvil.
En el
Data[i-lookback:i, 0].sum()
he puesto0
para referirse a la primera columna del conjunto de datos pero puedes poner cualquier columna que quieras en caso de que tengas más de una columna.fuente
De hecho, quería un comportamiento ligeramente diferente a la respuesta aceptada. Estaba construyendo un extractor de características de media móvil para una
sklearn
tubería, por lo que necesitaba que la salida de la media móvil tuviera la misma dimensión que la entrada. Lo que quiero es que la media móvil asuma que la serie permanece constante, es decir, una media móvil de[1,2,3,4,5]
con la ventana 2 daría[1.5,2.5,3.5,4.5,5.0]
.Para los vectores de columna (mi caso de uso) obtenemos
Y para matrices
Por supuesto, no es necesario asumir valores constantes para el relleno, pero hacerlo debería ser adecuado en la mayoría de los casos.
fuente
talib contiene una herramienta de promedio móvil simple, así como otras herramientas de promedio similares (es decir, promedio móvil exponencial). A continuación, se compara el método con algunas de las otras soluciones.
Una advertencia es que lo real debe tener elementos de
dtype = float
. De lo contrario, se genera el siguiente errorfuente
Aquí hay una implementación rápida usando numba (tenga en cuenta los tipos). Tenga en cuenta que contiene nans donde se desplazó.
fuente
fuente
Utilizo la solución de la respuesta aceptada , ligeramente modificada para tener la misma longitud para la salida que la entrada, o
pandas
la versión como se menciona en un comentario de otra respuesta. Resumo ambos aquí con un ejemplo reproducible para referencia futura:fuente
Al comparar la solución a continuación con la que usa cumsum of numpy, esta toma casi la mitad del tiempo . Esto se debe a que no necesita pasar por toda la matriz para hacer el cumsum y luego hacer toda la resta. Además, el cumsum puede ser " peligroso " si la matriz es enorme y el número es enorme ( posible desbordamiento ). Por supuesto, también aquí existe el peligro, pero al menos se suman solo los números esenciales.
fuente