HOWTO · Python

Media móvil para NumPy Array en Python

Este tutorial demuestra cómo calcular la media móvil para numpy arrays en python

En esta página

Una media móvil simple es la media de una ventana de tamaño fijo formada por valores consecutivos. Para una matriz de NumPy, numpy.convolve o numpy.cumsum permite calcularla directamente; bottleneck.move_mean y pandas con rolling().mean() son alternativas basadas en bibliotecas. Una ventana de cuatro significa que cada resultado resume cuatro valores de entrada contiguos. Las medias móviles suavizan las fluctuaciones a corto plazo y pueden facilitar la identificación de tendencias, mientras que una media móvil ponderada da más importancia a los datos recientes.

Los datos del ejemplo contienen 12 valores. El primer método devuelve un resultado por cada ventana completa de cuatro valores, por lo que el resultado tiene 9 valores. Elige el tamaño de ventana según la cantidad de observaciones que deba resumir cada media; cambiarlo modifica tanto el suavizado como el número de resultados para ventanas completas.

Simple Moving Average

Usa numpy.convolve para calcular una media móvil de matrices de NumPy

numpy.convolve calcula una convolución lineal. Aquí, la segunda matriz contiene cuatro unos; cada resultado de la convolución es la suma de una ventana de cuatro valores. Al dividir cada suma entre cuatro, se obtiene su media. El modo valid devuelve solo las ventanas que caben por completo en la entrada. Por eso, con 12 valores de entrada y una ventana de 4 se obtienen 9 resultados. Estos corresponden a las ventanas de izquierda a derecha: la primera calcula la media de las posiciones de entrada 0 a 3 y la última, de las posiciones 8 a 11.

import numpy as np


def moving_average(values, window):
    weights = np.ones(window) / window
    return np.convolve(values, weights, mode="valid")

data = np.array([10, 5, 8, 9, 15, 22, 26, 11, 15, 16, 18, 7])
print(moving_average(data, 4))
[ 8.    9.25 13.5  18.   18.5  18.5  17.   15.   14.  ]

Usa numpy.cumsum para calcular una media móvil de matrices de NumPy

Con una suma acumulada, se obtiene el total de cada ventana restando del total acumulado al final de la ventana el total acumulado anterior a ella. La primera ventana no tiene un total anterior que restar, por lo que la función comienza con el primer tramo completo. Así se obtienen las mismas 9 medias que con el ejemplo de numpy.convolve. Este método resulta útil para ver cómo se pueden calcular las sumas de las ventanas a partir de totales acumulados; dividir cada suma por el tamaño de la ventana la convierte en una media.

import numpy as np


def moving_average(values, window):
    cumulative = np.cumsum(values, dtype=float)
    cumulative[window:] -= cumulative[:-window]
    return cumulative[window - 1:] / window

data = np.array([10, 5, 8, 9, 15, 22, 26, 11, 15, 16, 18, 7])
print(moving_average(data, 4))
[ 8.    9.25 13.5  18.   18.5  18.5  17.   15.   14.  ]

Usa el módulo bottleneck para calcular una media móvil

El paquete bottleneck ofrece move_mean para calcular la media móvil de una matriz. Como, de forma predeterminada, se requiere una ventana completa, las tres primeras posiciones no tienen un resultado para una ventana de cuatro valores; la primera media aparece en el índice 3. El resultado conserva la longitud de la entrada y representa esas posiciones iniciales como nan. El ejemplo usa Bottleneck cuando está disponible e incluye una alternativa sencilla en Python puro para los entornos que no tienen ese paquete opcional. Este método es útil cuando se quiere conservar una posición de resultado por cada valor de entrada; los nan iniciales indican que todavía no se ha formado una ventana completa.

from importlib.util import find_spec


data = [10, 5, 8, 9, 15, 22, 26, 11, 15, 16, 18, 7]
window = 4

if find_spec("bottleneck") is not None:
    import bottleneck as bn

    result = bn.move_mean(data, window=window).tolist()
else:
    result = [float("nan")] * (window - 1)
    result.extend(
        sum(data[start:start + window]) / window
        for start in range(len(data) - window + 1)
    )

print(result)
[nan, nan, nan, 8.0, 9.25, 13.5, 18.0, 18.5, 18.5, 17.0, 15.0, 14.0]

Usa el módulo pandas para calcular una media móvil

Para datos de series temporales almacenados en una Serie de pandas, llama a rolling(4).mean() para calcular la media de cada ventana completa de cuatro valores. De forma predeterminada, la Serie conserva su longitud y su índice originales. Sus tres primeras entradas son NaN porque en esas posiciones aún no hay cuatro valores disponibles; la primera media calculada se alinea con el índice 3. Aquí aparecen los mismos valores que en los otros ejemplos, pero el índice de la Serie permite relacionar fácilmente cada resultado con su observación original. Si el tamaño de la ventana procede de una variable, puedes pasarlo a rolling().

import pandas as pd


data = [10, 5, 8, 9, 15, 22, 26, 11, 15, 16, 18, 7]
series = pd.Series(data)
print(series.rolling(4).mean())
0       NaN
1       NaN
2       NaN
3      8.00
4      9.25
5     13.50
6     18.00
7     18.50
8     18.50
9     17.00
10    15.00
11    14.00
dtype: float64