Manipuler une série temporelle avec pandas

Première leçon du cours Séries temporelles et prévision, en accès libre : environ 15 minutes, 3 exercices et 3 questions de quiz. C'est la leçon de base du catalogue ; dans l'espace étudiant, elle est réécrite pour ton profil.

Objectifs

  • Créer et indexer une série temporelle avec un DatetimeIndex
  • Changer de fréquence avec resample et agréger correctement
  • Calculer des fenêtres glissantes et des décalages (rolling, shift, diff)

DatetimeIndexRééchantillonnageFenêtres glissantesDécalage (lag)

Une série temporelle est une suite de mesures prises dans le temps : ventes quotidiennes, température horaire, nombre de connexions par minute. Ce qui la distingue d’un tableau classique, c’est que l’ordre des lignes porte de l’information. On ne mélange jamais les lignes, et l’on se demande toujours : quelle est la fréquence ? Y a-t-il des trous ?

Construire un DatetimeIndex

La première étape consiste à convertir la colonne de dates et à la placer en index :

import numpy as np
import pandas as pd

rng = np.random.default_rng(0)
df = pd.DataFrame({
    "date": pd.date_range("2024-01-01", periods=90, freq="D").astype(str),
    "ventes": rng.integers(50, 150, size=90),
})
df["date"] = pd.to_datetime(df["date"])   # texte -> datetime64
df = df.set_index("date").sort_index()     # index temporel trié

print(df.loc["2024-02"].head())            # tout le mois de février
print(df.loc["2024-01-10":"2024-01-15"])   # une plage de dates (bornes incluses)

Avec un DatetimeIndex, vous accédez aussi à des attributs utiles : df.index.day_of_week (0 = lundi ; l’ancien nom dayofweek est déprécié depuis pandas 3.1), df.index.month, df.index.year.

Changer de fréquence avec resample

resample regroupe les observations par période, un peu comme un groupby sur le temps. Il faut toujours préciser l’agrégation :

mensuel = df["ventes"].resample("ME").sum()      # total par fin de mois
hebdo_moy = df["ventes"].resample("W").mean()    # moyenne par semaine

Choisissez l’agrégation selon la nature de la mesure : on somme des volumes (ventes, visites) et on moyenne des niveaux (température, stock moyen). Depuis pandas 2.2, l’alias de fin de mois est "ME" ("MS" pour le début de mois) ; l’ancien "M" n’est plus accepté dans pandas 3.

Dans l’autre sens, passer à une fréquence plus fine (suréchantillonnage) crée des trous qu’il faut combler, par exemple avec .ffill() ou .interpolate().

Fenêtres glissantes et décalages

Une moyenne mobile lisse le bruit pour révéler la tendance :

df["moy_7j"] = df["ventes"].rolling(window=7).mean()   # NaN sur les 6 premières lignes
df["lag_1"] = df["ventes"].shift(1)                    # valeur de la veille
df["var_j"] = df["ventes"].diff()                      # ventes(t) - ventes(t-1)
df["var_pct"] = df["ventes"].pct_change()              # variation relative
  • rolling(7) regarde les 7 dernières valeurs, la valeur courante incluse. Les premières lignes valent NaN tant que la fenêtre n’est pas complète (paramètre min_periods pour assouplir).
  • shift(1) décale vers le bas : la ligne du 2 janvier reçoit la valeur du 1er janvier. C’est la brique de base des lags que nous utiliserons pour la prévision.
  • diff() est équivalent à serie - serie.shift(1).

Repérer les trous

Une série « propre » a une fréquence régulière. Pour vérifier :

complet = pd.date_range(df.index.min(), df.index.max(), freq="D")
manquants = complet.difference(df.index)
df = df.reindex(complet)      # les jours absents apparaissent en NaN

Rendre les trous explicites est préférable à les ignorer : un jour sans vente (0) n’est pas la même chose qu’un jour sans donnée (NaN).

À retenir

Index temporel trié, fréquence connue, agrégation adaptée, et prudence avec les fenêtres : ces quatre réflexes évitent la majorité des erreurs dans la suite du cours.

Exercices

Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.

  1. CodeDifficulté 1Python dans le navigateur2 indices

    Ventes mensuelles

    Écrivez la fonction ventes_mensuelles(df) qui reçoit un DataFrame indexé par date (fréquence journalière) avec une colonne ventes, et renvoie une Series des ventes totales par mois (alias de fin de mois "ME").

    import numpy as np
    import pandas as pd
    
    rng = np.random.default_rng(42)
    idx = pd.date_range("2024-01-01", periods=90, freq="D")
    df = pd.DataFrame({"ventes": rng.integers(50, 150, size=90)}, index=idx)
    
    def ventes_mensuelles(df):
        # TODO : rééchantillonner par mois et sommer
        pass
  2. CodeDifficulté 2Python dans le navigateur2 indices

    Moyenne mobile, lag et variation

    Écrivez ajouter_indicateurs(df) qui renvoie une copie du DataFrame avec trois nouvelles colonnes :

    • moy_7j : moyenne mobile des ventes sur 7 jours (fenêtre complète obligatoire) ;
    • lag_1 : les ventes de la veille ;
    • var_j : la différence ventes(t) - ventes(t-1).
    import numpy as np
    import pandas as pd
    
    rng = np.random.default_rng(7)
    idx = pd.date_range("2024-03-01", periods=30, freq="D")
    df = pd.DataFrame({"ventes": rng.normal(100, 10, 30).round(1)}, index=idx)
    
    def ajouter_indicateurs(df):
        out = df.copy()
        # TODO
        return out
  3. QCMDifficulté 11 indice

    Resample ou rolling ?

    Vous voulez un tableau avec une ligne par semaine contenant le total des ventes. Quelle instruction utilisez-vous ?

    • df['ventes'].rolling(7).sum()
    • df['ventes'].resample('W').sum()
    • df['ventes'].shift(7)
    • df['ventes'].diff(7)

Quiz de fin de leçon

  1. Que contient la ligne du 10 mars après df[‘ventes’].shift(1) ?

    • Les ventes du 11 mars
    • Les ventes du 9 mars
    • La moyenne des ventes jusqu'au 10 mars
    • NaN
  2. Pourquoi les 6 premières valeurs de rolling(7).mean() sont-elles NaN ?

    • Parce que pandas ignore le début des séries
    • Parce que la fenêtre de 7 observations n'est pas encore complète
    • Parce que l'index n'est pas trié
    • Parce qu'il faut utiliser resample avant
  3. Pour passer des températures horaires à une valeur par jour, quelle agrégation est la plus pertinente ?

    • sum
    • mean
    • count
    • first

La suite du cours

  1. Tendance, saisonnalité et stationnarité18 min
  2. Baselines et évaluation d'une prévision15 min
  3. Modèles classiques : lissage exponentiel et ARIMA20 min
  4. Prévoir avec le machine learning et faire un backtest20 min

Séries temporelles et prévision · Avancé · 3 h 28