series-temporales-python

Una guía para el análisis de series temporales en Python

El análisis de series temporales es una tarea común para los científicos de datos. Esta guía le presentará sus conceptos clave en Python.

En todas las industrias, las organizaciones suelen utilizar datos de series temporales, lo que significa cualquier información recopilada durante un intervalo de tiempo regular, en sus operaciones. Los ejemplos incluyen los precios diarios de las acciones, las tasas de consumo de energía, las métricas de participación en las redes sociales y la demanda minorista, entre otros. El análisis de datos de series temporales brinda información como tendencias, patrones estacionales y pronósticos sobre eventos futuros que pueden ayudar a generar ganancias. Por ejemplo, al comprender las tendencias estacionales en la demanda de productos minoristas, las empresas pueden planificar promociones para maximizar las ventas durante todo el año.

Al analizar datos de series temporales, debe realizar una serie de pasos. Primero, debe verificar la estacionariedad y la autocorrelación. La estacionariedad es una forma de medir si los datos tienen patrones estructurales como tendencias estacionales. La autocorrelación ocurre cuando los valores futuros en una serie de tiempo dependen linealmente de los valores pasados. Debe verificar ambos en los datos de series de tiempo porque son suposiciones hechas por muchos métodos ampliamente utilizados en el análisis de series de tiempo. Por ejemplo, el método de promedio móvil integrado autorregresivo (ARIMA) para pronosticar series de tiempo asume estacionariedad. Además, la regresión lineal para el pronóstico de series de tiempo asume que los datos no tienen autocorrelación. Entonces, antes de realizar estos procesos, debe saber si los datos son viables para el análisis.

Durante un análisis de series temporales, también debe realizar una descomposición de tendencias y pronosticar valores futuros. La descomposición le permite visualizar tendencias en sus datos, lo cual es una excelente manera de explicar claramente su comportamiento. Finalmente, la previsión le permite anticipar eventos futuros que pueden ayudar en la toma de decisiones. Puede usar muchas técnicas diferentes para el pronóstico de series de tiempo, pero aquí discutiremos el promedio móvil integrado autorregresivo (ARIMA).

Trabajaremos con datos de series temporales de pasajeros de aerolíneas disponibles públicamente, que se pueden encontrar aquí.


Análisis de series temporales

En todas las industrias, las organizaciones suelen utilizar datos de series temporales, lo que significa cualquier información recopilada durante un intervalo de tiempo regular, en sus operaciones. Los ejemplos incluyen los precios diarios de las acciones, las tasas de consumo de energía, las métricas de participación en las redes sociales y la demanda minorista, entre otros. El análisis de datos de series temporales brinda información como tendencias, patrones estacionales y pronósticos sobre eventos futuros que pueden ayudar a generar ganancias. Por ejemplo, al comprender las tendencias estacionales en la demanda de productos minoristas, las empresas pueden planificar promociones para maximizar las ventas durante todo el año. 

Lectura y visualización de datos

Para comenzar, importemos la biblioteca de Pandas y leamos los datos de los pasajeros de la aerolínea en un marco de datos:

import pandas as pd 
df = pd.read_csv("AirPassengers.csv")

Ahora, mostremos las primeras cinco filas de datos usando el método head() del marco de datos:

print(df.head())
serie-temporal-python

Podemos ver que los datos contienen una columna etiquetada como «Mes» que contiene fechas. En esa columna, las fechas tienen el formato año-mes. También vemos que los datos comienzan en el año 1949.

La segunda columna tiene la etiqueta «#Passengers» y contiene la cantidad de pasajeros para el año-mes. Echemos un vistazo a los últimos cinco registros de datos usando el método tail():

print(df.tail())
serie-temporal-python

Vemos a partir de este proceso que los datos terminan en 1960.

Lo siguiente que querremos hacer es convertir la columna del mes en un objeto de fecha y hora. Esto le permitirá obtener mediante programación valores de tiempo como el año o el mes para cada registro. Para hacer esto, usamos el método Pandas to_datetime():

df['Month'] = pd.to_datetime(df['Month'], format='%Y-%m')
print(df.head())
serie-temporal-python

Tenga en cuenta que este proceso inserta automáticamente el primer día de cada mes, que es básicamente un valor ficticio ya que no tenemos datos de pasajeros diarios.

Lo siguiente que podemos hacer es convertir la columna del mes en un índice. Esto nos permitirá trabajar más fácilmente con algunos de los paquetes que cubriremos más adelante:

df.index = df['Month']
del df['Month']
print(df.head())
serie-temporal-python
Imagen: Captura de pantalla

A continuación, generemos un gráfico de series de tiempo usando Seaborn y Matplotlib. Esto nos permitirá visualizar los datos de la serie temporal. Primero, importemos Matplotlib y Seaborn:

import matplotlib.pyplot as plt
import seaborn as sns 

A continuación, generemos un diagrama de líneas usando Seaborn:

sns.lineplot(df)

Y etiqueta el eje y con Matplotlib:

plt.ylabel(“Number of Passengers”)
serie-temporal-python

Te puede interesar: ¿Necesita realizar un análisis de datos financieros? Por qué Python es tu mejor herramienta.

Estacionariedad

La estacionariedad es una parte clave del análisis de series de tiempo. En pocas palabras, la estacionariedad significa que la forma en que cambian los datos de las series temporales es constante. Una serie temporal estacionaria no tendrá tendencias ni patrones estacionales. Debe verificar la estacionariedad porque no solo facilita el modelado de series temporales, sino que es una suposición subyacente en muchos métodos de series temporales. Específicamente, se asume la estacionariedad para una amplia variedad de métodos de pronóstico de series de tiempo que incluyen el promedio móvil autorregresivo (ARMA), ARIMA y ARIMA estacional (SARIMA).

Usaremos la prueba de Dickey Fuller para verificar la estacionariedad en nuestros datos. Esta prueba generará valores críticos y un p-valor, que nos permitirán aceptar o rechazar la hipótesis nula de que no existe estacionariedad. Si rechazamos la hipótesis nula, eso significa que aceptamos la alternativa, que establece que hay estacionariedad.

Estos valores nos permiten probar el grado en que los valores presentes cambian con los valores pasados. Si no hay estacionariedad en el conjunto de datos, un cambio en los valores presentes no provocará un cambio significativo en los valores pasados.

Probemos la estacionariedad en los datos de pasajeros de nuestra aerolínea. Para empezar, calculemos una media móvil de siete meses:

rolling_mean = df.rolling(7).mean()
rolling_std = df.rolling(7).std()

A continuación, superpongamos nuestra serie temporal con la media móvil de siete meses y la desviación estándar móvil de siete meses. Primero, hagamos un diagrama de Matplotlib de nuestra serie de tiempo:

plt.plot(df, color="blue",label="Original Passenger Data")

Entonces la media rodante:

plt.plot(rolling_mean, color="red", label="Rolling Mean Passenger Number")

Y finalmente, la desviación estándar móvil:

plt.plot(rolling_std, color="black", label = "Rolling Standard Deviation in Passenger Number")

A continuación, agreguemos un título:

plt.title("Passenger Time Series, Rolling Mean, Standard Deviation")

Y una leyenda:

plt.legend(loc="best")
serie-temporal-python

A continuación, importemos la prueba Dickey-Fuller aumentada del paquete statsmodels. La documentación para la prueba se puede encontrar aquí.

from statsmodels.tsa.stattools import adfuller

A continuación, pasemos nuestro marco de datos al método adfuller. Aquí, especificamos el parámetro de retraso automático como «AIC», lo que significa que el retraso se elige para minimizar el criterio de información:

adft = adfuller(df,autolag="AIC")

A continuación, almacenemos nuestros resultados en un marco de datos para mostrarlo:

output_df = pd.DataFrame({"Values":[adft[0],adft[1],adft[2],adft[3], adft[4]['1%'], adft[4]['5%'], adft[4]['10%']]  , "Metric":["Test Statistics","p-value","No. of lags used","Number of observations used", 
                                                        "critical value (1%)", "critical value (5%)", "critical value (10%)"]})
print(output_df)
serie-temporal-python

Podemos ver que nuestros datos no son estacionarios por el hecho de que nuestro valor p es mayor al 5 por ciento y el estadístico de prueba es mayor que el valor crítico. También podemos sacar estas conclusiones de la inspección de los datos, ya que vemos una tendencia clara y creciente en el número de pasajeros.

Autocorrelación

La verificación de la autocorrelación en los datos de series temporales es otra parte importante del proceso analítico. Esta es una medida de cuán correlacionados están los datos de series temporales en un momento dado con valores pasados, lo que tiene enormes implicaciones en muchas industrias. Por ejemplo, si nuestros datos de pasajeros tienen una fuerte autocorrelación, podemos suponer que un número elevado de pasajeros hoy sugiere una gran probabilidad de que también lo sea mañana.

El marco de datos de Pandas tiene un método de autocorrelación que podemos usar para calcular la autocorrelación en nuestros datos de pasajeros. Hagamos esto con un retraso de un mes:

autocorrelation_lag1 = df['#Passengers'].autocorr(lag=1)
print("One Month Lag: ", autocorrelation_lag1)
análisis de series temporales

Ahora, probemos tres, seis y nueve meses:

autocorrelation_lag3 = df['#Passengers'].autocorr(lag=3)
print("Three Month Lag: ", autocorrelation_lag3)

autocorrelation_lag6 = df['#Passengers'].autocorr(lag=6)
print("Six Month Lag: ", autocorrelation_lag6)

autocorrelation_lag9 = df['#Passengers'].autocorr(lag=9)
print("Nine Month Lag: ", autocorrelation_lag9)
análisis de series temporales

Vemos que, incluso con un retraso de nueve meses, los datos están altamente autocorrelacionados. Esta es una ilustración más de las tendencias a corto y largo plazo en los datos.

Descomposición

La descomposición de tendencias es otra forma útil de visualizar las tendencias en datos de series temporales. Para continuar, importemos season_decompose del paquete statsmodels:

from statsmodels.tsa.seasonal import seasonal_decompose

A continuación, pasemos nuestro marco de datos al método season_decompose y tracemos el resultado:

decompose = seasonal_decompose(df['#Passengers'],model='additive', period=7)
decompose.plot()
plt.show()
serie-temporal-python

A partir de este gráfico, podemos ver claramente la tendencia creciente en el número de pasajeros y los patrones de estacionalidad en el aumento y la caída de los valores cada año.

Pronóstico

El pronóstico de series de tiempo nos permite predecir valores futuros en una serie de tiempo dados datos actuales y pasados. Aquí, usaremos el método ARIMA para pronosticar el número de pasajeros, lo que nos permite pronosticar valores futuros en términos de una combinación lineal de valores pasados. Usaremos el paquete auto_arima, que nos permitirá renunciar al lento proceso de ajuste de hiperparámetros.

Primero, dividamos nuestros datos para entrenamiento y prueba y visualicemos la división:

df['Date'] = df.index
train = df[df['Date'] < pd.to_datetime("1960-08", format='%Y-%m')]
train['train'] = train['#Passengers']
del train['Date']
del train['#Passengers']
test = df[df['Date'] >= pd.to_datetime("1960-08", format='%Y-%m')]
del test['Date']
test['test'] = test['#Passengers']
del test['#Passengers']
plt.plot(train, color = "black")
plt.plot(test, color = "red")
plt.title("Train/Test split for Passenger Data")
plt.ylabel("Passenger Number")
plt.xlabel('Year-Month')
sns.set()
plt.show()
serie-temporal-python

La línea negra corresponde a nuestros datos de entrenamiento y la línea roja corresponde a nuestros datos de prueba.

Importemos auto_arima desde el paquete pdmarima, entrenemos nuestro modelo y generemos predicciones:

from pmdarima.arima import auto_arima
model = auto_arima(train, trace=True, error_action='ignore', suppress_warnings=True)
model.fit(train)
forecast = model.predict(n_periods=len(test))
forecast = pd.DataFrame(forecast,index = test.index,columns=['Prediction'])

A continuación se muestra una muestra truncada de la salida:

serie-temporal-python

Ahora, mostremos la salida de nuestro modelo:

serie-temporal-python

Nuestras predicciones se muestran en verde y los valores reales se muestran en naranja.

Finalmente, calculemos el error cuadrático medio (RMSE):

from math import sqrt
from sklearn.metrics import mean_squared_error
rms = sqrt(mean_squared_error(test,forecast))
print("RMSE: ", rms)
serie-temporal-python

Ciencia maestra de datos: La guía definitiva de curvas ROC y AUC

Análisis de series temporales

Realizar análisis de datos de series temporales es una tarea que casi todos los científicos de datos enfrentarán en su carrera. Tener una buena comprensión de las herramientas y los métodos de análisis puede permitir que los científicos de datos descubran tendencias, anticipen eventos y, en consecuencia, informen la toma de decisiones. Comprender los patrones de estacionalidad a través de la estacionariedad, la autocorrelación y la descomposición de tendencias puede guiar la planificación de promociones a lo largo del año, lo que puede mejorar las ganancias de las empresas. Por último, la previsión de series temporales es una forma eficaz de anticipar eventos futuros en sus datos de series temporales, que también pueden tener un impacto significativo en la toma de decisiones. Estos tipos de análisis son invaluables para cualquier científico de datos o equipo de ciencia de datos que busque aportar valor a su empresa con datos de series temporales. El código de esta publicación está disponible en GitHub.