Guide de visualisation des séries chronologiques avec Python 3

introduction

L’analyse des séries chronologiques appartient à une branche de la statistique qui implique l’étude de données ordonnées, souvent temporelles. Lorsqu'elle est appliquée de manière pertinente, l'analyse en série chronologique peut révéler des tendances inattendues, extraire des statistiques utiles et même prévoir les tendances à venir. Pour ces raisons, il est appliqué à de nombreux domaines, notamment l'économie, les prévisions météorologiques et la planification de la capacité.

Dans ce didacticiel, nous présenterons quelques techniques courantes utilisées dans l'analyse de séries chronologiques et expliquerons les étapes itératives requises pour manipuler et visualiser des données de séries chronologiques.

Conditions préalables

Ce guide explique comment effectuer des analyses chronologiques sur un poste de travail local ou un serveur distant. Travailler avec de grands ensembles de données peut demander beaucoup de mémoire, donc dans les deux cas, l'ordinateur aura besoin d'au moins2GB of memory pour effectuer certains des calculs de ce guide.

Pour ce didacticiel, nous utiliseronsJupyter Notebook pour travailler avec les données. Si vous ne l'avez pas déjà, vous devriez suivre nostutorial to install and set up Jupyter Notebook for Python 3.

[[step-1 -—- Installing-packages]] == Étape 1 - Installation des packages

Nous allons exploiter la bibliothèquepandas, qui offre beaucoup de flexibilité lors de la manipulation des données, et la bibliothèquestatsmodels, qui nous permet d'effectuer des calculs statistiques en Python. Utilisées ensemble, ces deux bibliothèques étendent Python pour offrir une plus grande fonctionnalité et augmenter considérablement notre boîte à outils d’analyse.

Comme avec les autres packages Python, nous pouvons installerpandas etstatsmodels avecpip. Premièrement, passons à notre environnement de programmation local ou à notre environnement de programmation basé sur serveur:

cd environments
. my_env/bin/activate

À partir de là, créons un nouveau répertoire pour notre projet. Nous l'appelleronstimeseries puis nous nous déplacerons dans le répertoire. Si vous appelez le projet un nom différent, assurez-vous de remplacer votre nom partimeseries tout au long du guide

mkdir timeseries
cd timeseries

Nous pouvons maintenant installerpandas,statsmodels et le package de traçage de donnéesmatplotlib. Leurs dépendances seront également installées:

pip install pandas statsmodels matplotlib

À ce stade, nous sommes maintenant prêts à commencer à travailler avecpandas etstatsmodels.

[[step-2 -—- loading-time-series-data]] == Étape 2 - Chargement des données chronologiques

Pour commencer à utiliser nos données, nous allons démarrer Jupyter Notebook:

jupyter notebook

Pour créer un nouveau fichier notebook, sélectionnezNew>Python 3 dans le menu déroulant en haut à droite:

Create a new Python 3 notebook

Cela ouvrira un cahier qui nous permettra de charger les bibliothèques requises (notez les raccourcis standard utilisés pour référencerpandas,matplotlib etstatsmodels). En haut de notre cahier, nous devrions écrire ce qui suit:

import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt

Après chaque bloc de code de ce didacticiel, vous devez taperALT + ENTER pour exécuter le code et vous déplacer dans un nouveau bloc de code dans votre bloc-notes.

De manière pratique,statsmodels est livré avec des ensembles de données intégrés, ce qui nous permet de charger un ensemble de données chronologiques directement en mémoire.

Nous allons travailler avec un ensemble de données appelé «CO2 atmosphérique provenant d’échantillons d’air continus à l’observatoire du Mauna Loa, Hawaii, États-Unis», qui a recueilli des échantillons de CO2 de mars 1958 à décembre 2001. Nous pouvons apporter ces données comme suit:

data = sm.datasets.co2.load_pandas()
co2 = data.data

Voyons à quoi ressemblent les 5 premières lignes de nos séries chronologiques:

print(co2.head(5))
Output              co2
1958-03-29  316.1
1958-04-05  317.3
1958-04-12  317.6
1958-04-19  317.5
1958-04-26  316.4

Avec nos packages importés et le jeu de données CO2 prêt à l'emploi, nous pouvons passer à l'indexation de nos données.

[[step-3 -—- indexing-with-time-series-data]] == Étape 3 - Indexation avec des données de séries chronologiques

Vous avez peut-être remarqué que les dates ont été définies comme index de notrepandas DataFrame. Lorsque vous travaillez avec des données chronologiques en Python, vous devez vous assurer que les dates sont utilisées comme index. Veillez donc à toujours vérifier cela, ce que nous pouvons faire en exécutant les opérations suivantes:

co2.index
OutputDatetimeIndex(['1958-03-29', '1958-04-05', '1958-04-12', '1958-04-19',
               '1958-04-26', '1958-05-03', '1958-05-10', '1958-05-17',
               '1958-05-24', '1958-05-31',
               ...
               '2001-10-27', '2001-11-03', '2001-11-10', '2001-11-17',
               '2001-11-24', '2001-12-01', '2001-12-08', '2001-12-15',
               '2001-12-22', '2001-12-29'],
              dtype='datetime64[ns]', length=2284, freq='W-SAT')

Le champdtype=datetime[ns] confirme que notre index est composé d'objets horodatés, tandis quelength=2284 etfreq='W-SAT' nous indique que nous avons 2284 horodatages hebdomadaires à partir du samedi.

Il est parfois difficile de travailler avec les données hebdomadaires. Par conséquent, utilisons plutôt les moyennes mensuelles de notre série chronologique. Cela peut être obtenu en utilisant la fonction pratiqueresample, qui nous permet de regrouper les séries chronologiques en tranches (1 mois), d'appliquer unfunction sur chaque groupe (moyenne) et de combiner le résultat ( une ligne par groupe).

y = co2['co2'].resample('MS').mean()

Ici, le termeMS signifie que nous regroupons les données dans des buckets par mois et nous garantissons que nous utilisons le début de chaque mois comme horodatage:

y.head(5)
Output1958-03-01    316.100
1958-04-01    317.200
1958-05-01    317.120
1958-06-01    315.800
1958-07-01    315.625
Freq: MS, Name: co2, dtype: float64

Une caractéristique intéressante depandas est sa capacité à gérer les indices d'horodatage, ce qui nous permet de découper rapidement nos données. Par exemple, nous pouvons découper notre ensemble de données pour ne récupérer que les points de données qui viennent après l'année1990:

y['1990':]
Output1990-01-01    353.650
1990-02-01    354.650
               ...
2001-11-01    369.375
2001-12-01    371.020
Freq: MS, Name: co2, dtype: float64

Ou, nous pouvons découper notre ensemble de données pour récupérer uniquement les points de données entre octobre1995 et octobre1996:

y['1995-10-01':'1996-10-01']
Output1995-10-01    357.850
1995-11-01    359.475
1995-12-01    360.700
1996-01-01    362.025
1996-02-01    363.175
1996-03-01    364.060
1996-04-01    364.700
1996-05-01    365.325
1996-06-01    364.880
1996-07-01    363.475
1996-08-01    361.320
1996-09-01    359.400
1996-10-01    359.625
Freq: MS, Name: co2, dtype: float64

Avec nos données correctement indexées pour travailler avec des données temporelles, nous pouvons passer aux valeurs de traitement qui peuvent être manquantes.

[[step-4 -—- handling-missing-values-in-time-series-data]] == Étape 4 - Gestion des valeurs manquantes dans les données de séries chronologiques

Les données du monde réel ont tendance à être compliquées. Comme on peut le voir sur le graphique, il n’est pas rare que les données de séries chronologiques contiennent des valeurs manquantes. Le moyen le plus simple de vérifier ces informations consiste à tracer directement les données ou à l'aide de la commande ci-dessous qui révélera les données manquantes dans la sortie:

y.isnull().sum()
Output5

Cette sortie nous indique qu'il y a 5 mois avec des valeurs manquantes dans notre série chronologique.

En règle générale, nous devrions «renseigner» les valeurs manquantes si elles ne sont pas trop nombreuses afin de ne pas avoir de lacunes dans les données. Nous pouvons le faire enpandas en utilisant lesfillna() command. Par souci de simplicité, nous pouvons renseigner les valeurs manquantes avec la valeur non nulle la plus proche de notre série chronologique, bien qu'il soit important de noter qu'une moyenne glissante serait parfois préférable.

y = y.fillna(y.bfill())

Avec les valeurs manquantes renseignées, nous pouvons à nouveau vérifier s'il existe des valeurs null pour nous assurer que notre opération a fonctionné:

y.isnull().sum()
Output0

Après avoir effectué ces opérations, nous constatons que nous avons rempli toutes les valeurs manquantes de notre série chronologique.

[[step-5 -—- visualizing-time-series-data]] == Étape 5 - Visualisation des données de séries chronologiques

Lorsque vous travaillez avec des données chronologiques, vous pouvez en révéler beaucoup en les visualisant. Quelques choses à surveiller sont:

  • seasonality:does the data display a clear periodic pattern?

  • trend:does the data follow a consistent upwards or downward slope?

  • noise:are there any outlier points or missing values that are not consistent with the rest of the data?

Nous pouvons utiliser le wrapperpandas autour de l'APImatplotlib pour afficher un tracé de notre ensemble de données:

y.plot(figsize=(15, 6))
plt.show()

Timeseries Visualization Figure 1

Certains modèles distincts apparaissent lorsque nous traçons les données. La série chronologique présente un modèle de saisonnalité évident, ainsi qu'une tendance générale à la hausse. Nous pouvons également visualiser nos données à l'aide d'une méthode appelée décomposition en série chronologique. Comme son nom l'indique, la décomposition de séries chronologiques nous permet de décomposer nos séries chronologiques en trois composantes distinctes: la tendance, la saisonnalité et le bruit.

Heureusement,statsmodels fournit la fonction pratiqueseasonal_decompose pour effectuer une décomposition saisonnière prête à l'emploi. Si vous souhaitez en savoir plus, vous trouverez la référence pour son implémentation d'origine dans l'article suivant, «http://www.wessa.net/download/stl.pdf[STL: une procédure de décomposition saisonnière basée sur Loess. ]. "

Le script ci-dessous montre comment effectuer une décomposition saisonnière de séries temporelles en Python. Par défaut,seasonal_decompose renvoie un chiffre de taille relativement petite, donc les deux premières lignes de ce bloc de code garantissent que le chiffre de sortie est suffisamment grand pour que nous puissions le visualiser.

from pylab import rcParams
rcParams['figure.figsize'] = 11, 9

decomposition = sm.tsa.seasonal_decompose(y, model='additive')
fig = decomposition.plot()
plt.show()

Timeseries Seasonal-Trend Decomposition Visualization Figure 2

L'utilisation de la décomposition en série chronologique permet d'identifier plus facilement une moyenne ou une variation changeante des données. Le graphique ci-dessus montre clairement la tendance à la hausse de nos données, ainsi que sa saisonnalité annuelle. Ceux-ci peuvent être utilisés pour comprendre lesstructure de notre série chronologique. L’intuition derrière la décomposition en séries chronologiques est importante, car de nombreuses méthodes de prévision s’appuient sur ce concept de décomposition structurée pour produire des prévisions.

Conclusion

Si vous avez suivi ce guide, vous avez maintenant une expérience de la visualisation et de la manipulation de données chronologiques en Python.

Pour améliorer encore vos compétences, vous pouvez charger un autre jeu de données et répéter toutes les étapes de ce tutoriel. Par exemple, vous souhaiterez peut-être lire un fichier CSV en utilisant la bibliothèquepandas ou utiliser le jeu de donnéessunspots qui est préchargé avec la bibliothèquestatsmodels:data = sm.datasets.sunspots.load_pandas().data.