Fenêtres cumulées
Calculez des statistiques cumulées incluant toutes les lignes depuis le début jusqu’à chaque point avec expanding().sum().
Fenêtres cumulées est une leçon Pandas & NumPy Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Pandas & NumPy Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Pandas & NumPy Academy comprend 4 leçons au total.
Qu’est-ce qu’une fenêtre extensible ?
Une fenêtre extensible inclut toutes les lignes depuis le tout début de la Series jusqu’à la ligne actuelle : la fenêtre s’agrandit à chaque nouvelle ligne au lieu de rester fixe. À la ligne 0, elle ne contient qu’une valeur ; à la ligne 5, elle en contient six ; à la ligne 100, elle en contient 101. Les fenêtres extensibles servent à calculer des statistiques cumulées représentant le total cumulé, la moyenne cumulée ou le maximum cumulé depuis le début du jeu de données jusqu’au moment présent.
import pandas as pd
import numpy as np
sales = pd.Series(
[100, 150, 120, 200, 180, 160, 220, 190],
index=pd.date_range('2024-01-01', periods=8)
)
# Expanding mean — grows with each row
df = pd.DataFrame({'sales': sales})
df['cumulative_mean'] = df['sales'].expanding().mean()
print(df)La méthode expanding()
Series.expanding(min_periods=1) renvoie un objet Expanding. Le paramètre min_periods (1 par défaut) définit le nombre minimal d’observations nécessaires pour obtenir le premier résultat différent de NaN. Contrairement à rolling(n), la fenêtre de expanding() n’est pas fixe : elle commence toujours au début. Vous pouvez enchaîner n’importe quelle agrégation : .sum(), .mean(), .std(), .min(), .max().
import pandas as pd
import numpy as np
np.random.seed(42)
monthly_revenue = pd.Series(
np.random.randint(500, 1500, 12),
index=pd.date_range('2024-01', periods=12, freq='ME'),
name='revenue'
)
df = pd.DataFrame({'revenue': monthly_revenue})
df['cumsum'] = df['revenue'].expanding().sum()
df['cummean'] = df['revenue'].expanding().mean()
df['cummax'] = df['revenue'].expanding().max()
df['cummin'] = df['revenue'].expanding().min()
print(df)cumsum, cumprod, cummax et cummin de Pandas
Pour les statistiques cumulées les plus courantes, Pandas fournit des méthodes directes sur les Series et les DataFrame, sans nécessiter expanding() : cumsum(), cumprod(), cummax() et cummin(). Ces implémentations optimisées sont légèrement plus rapides que leurs équivalents expanding(). Utilisez ces raccourcis pour les indicateurs courants, comme le chiffre d’affaires depuis le début de l’année (cumsum) ou le prix maximal historique (cummax).
import pandas as pd
import numpy as np
prices = pd.Series(
[100, 95, 110, 105, 120, 115, 130, 125],
index=pd.date_range('2024-01-01', periods=8)
)
df = pd.DataFrame({'price': prices})
df['cummax'] = df['price'].cummax() # all-time high
df['cummin'] = df['price'].cummin() # all-time low
df['cumsum'] = df['price'].cumsum() # cumulative total
df['cumprod'] = (1 + df['price'].pct_change()).cumprod() # growth index
print(df.round(3))Calcul depuis le début de l’année avec expanding
Le chiffre d’affaires depuis le début de l’année (YTD) est un cas d’utilisation classique des fenêtres extensibles. Pour chaque jour, vous voulez calculer la somme de tous les revenus depuis le 1er janvier de l’année en cours jusqu’à ce jour. Il suffit d’appliquer cumsum() à chaque groupe annuel. Implémentez cela avec groupby(year).cumsum() : le cumsum est réinitialisé au début de chaque année civile, puis s’accumule tout au long de l’année.
import pandas as pd
import numpy as np
np.random.seed(0)
dates = pd.date_range('2023-01-01', '2024-06-30', freq='ME')
daily = pd.DataFrame({
'date': dates,
'revenue': np.random.randint(100, 500, len(dates))
})
# Year-to-date cumulative revenue
daily['year'] = daily['date'].dt.year
daily['ytd_revenue'] = daily.groupby('year')['revenue'].cumsum()
daily = daily.drop(columns='year')
print(daily.tail(10).to_string(index=False))Écart-type avec une fenêtre extensible
expanding().std() calcule l’écart-type cumulé à partir de toutes les données depuis le début jusqu’à la ligne actuelle. Cela permet de surveiller si la variabilité d’un indicateur augmente ou diminue au fil du temps, par exemple pour suivre si les ventes quotidiennes d’un produit deviennent plus ou moins prévisibles à mesure que l’activité mûrit. Contrairement à rolling std, qui ne reflète que la variabilité récente, expanding std prend en compte toute la dispersion historique.
import pandas as pd
import numpy as np
np.random.seed(42)
sales = pd.Series(
np.concatenate([
np.random.normal(100, 5, 30), # stable period
np.random.normal(100, 25, 30) # volatile period
]),
index=pd.date_range('2024-01-01', periods=60)
)
df = pd.DataFrame({'sales': sales})
df['expanding_std'] = df['sales'].expanding().std()
df['rolling_30d_std'] = df['sales'].rolling(30).std()
print(df.tail(10).round(2))Comparer rolling et expanding
La distinction essentielle est la suivante : les fenêtres glissantes reflètent les performances récentes (les n derniers jours) et sont peu influencées par les données anciennes, tandis que les fenêtres extensibles intègrent tout l’historique et convergent donc lentement vers des valeurs stables. Utilisez rolling lorsque vous vous intéressez aux tendances récentes : une moyenne mobile sur 7 jours réagit davantage aux changements récents qu’une moyenne sur 90 jours. Utilisez expanding lorsque vous voulez des statistiques historiques ou des indicateurs YTD qui ne doivent jamais oublier les données antérieures.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(10)
data = pd.Series(
np.random.randn(60).cumsum() + 50,
index=pd.date_range('2024-01-01', periods=60)
)
df = pd.DataFrame({'value': data})
df['rolling_10'] = data.rolling(10).mean()
df['expanding'] = data.expanding().mean()
df.plot(figsize=(12, 5), title='Rolling 10-day Mean vs. Expanding Mean')
plt.ylabel('Value')
plt.show()Apply avec expanding pour des statistiques cumulées personnalisées
expanding().apply(func) applique une fonction personnalisée à toutes les données depuis le début jusqu’à la ligne actuelle, exactement comme rolling().apply(). Cela permet de calculer des statistiques cumulées qui ne sont pas disponibles parmi les fonctions intégrées, par exemple le coefficient de variation cumulé (std/mean), la médiane cumulée ou un ratio de Sharpe cumulé. La fonction reçoit un tableau NumPy contenant toutes les valeurs observées jusqu’alors et doit renvoyer un scalaire.
import pandas as pd
import numpy as np
np.random.seed(0)
returns = pd.Series(
np.random.normal(0.001, 0.02, 60),
index=pd.date_range('2024-01-01', periods=60)
)
# Cumulative Sharpe ratio (mean/std of returns)
def sharpe(arr):
if len(arr) < 2:
return float('nan')
return arr.mean() / arr.std() * (252 ** 0.5) # annualised
df = pd.DataFrame({'returns': returns})
df['cum_sharpe'] = df['returns'].expanding().apply(sharpe, raw=True)
print(df.tail(8).round(4))Fenêtres extensibles et gestion des NaN
Par défaut, les fenêtres extensibles ignorent les valeurs NaN : un NaN au milieu de la Series est ignoré lors du calcul de la somme ou de la moyenne cumulée. Vous pouvez le vérifier avec skipna=True (valeur par défaut dans la plupart des agrégations Pandas). Lorsque vos séries temporelles contiennent de vraies valeurs manquantes, par exemple en l’absence de transactions le week-end, les statistiques extensibles sont calculées uniquement à partir des valeurs non NaN observées jusqu’alors, ce qui correspond généralement au comportement souhaité.
import pandas as pd
import numpy as np
data = pd.Series([10, np.nan, 20, 30, np.nan, 40, 50])
# cumsum skips NaN by default
df = pd.DataFrame({'value': data})
df['cumsum'] = df['value'].cumsum() # NaN propagates in cumsum!
df['expanding_sum'] = df['value'].expanding().sum() # NaN skipped
print(df)
print('\nNote: cumsum propagates NaN; expanding().sum() skips it.')Fenêtres extensibles pour les références cumulées
Les fenêtres extensibles sont idéales pour calculer des références cumulées : le maximum historique, le meilleur trimestre jamais réalisé ou le taux d’erreur le plus faible depuis le lancement. Ces indicateurs clés doivent conserver toutes les valeurs historiques ; une fenêtre glissante oublierait les anciens enregistrements. L’utilisation de cummax() ou cummin() renvoie la meilleure (ou la pire) valeur cumulée à chaque instant, ce qui facilite le suivi de l’établissement de nouveaux records.
import pandas as pd
import numpy as np
np.random.seed(5)
sales = pd.Series(
np.random.randint(100, 300, 20),
index=pd.date_range('2024-01-01', periods=20),
name='daily_sales'
)
df = pd.DataFrame({'sales': sales})
df['all_time_max'] = df['sales'].cummax()
df['new_record'] = df['sales'] == df['all_time_max']
print('Days where a new sales record was set:')
print(df[df['new_record']].drop(columns='new_record'))Exemple pratique : rendements cumulés
En finance, les rendements cumulés indiquent la croissance d’un investissement depuis sa date de départ jusqu’à chaque date suivante. À partir des rendements quotidiens en pourcentage, le produit cumulé de (1 + daily_return) donne le facteur de croissance total. Un produit extensible est ici plus naturel qu’un produit glissant : vous voulez suivre la croissance totale depuis le lancement, et non uniquement celle des n derniers jours.
import pandas as pd
import numpy as np
np.random.seed(7)
start_price = 100
daily_returns = pd.Series(
np.random.normal(0.0005, 0.015, 252),
index=pd.date_range('2024-01-01', periods=252)
)
# Cumulative return = product of (1 + r_i)
cum_returns = (1 + daily_returns).cumprod()
portfolio_value = start_price * cum_returns
print(f'Start value: ${start_price:.2f}')
print(f'End value: ${portfolio_value.iloc[-1]:.2f}')
print(f'Total return: {(portfolio_value.iloc[-1]/start_price - 1)*100:.1f}%')Quand utiliser expanding, rolling ou cumsum
Voici quelques recommandations pour choisir la bonne approche :
- Utilisez
cumsum() / cummax() / cummin()pour les agrégations cumulées simples : ce sont les options les plus rapides. - Utilisez
expanding().mean() / std()lorsque vous avez besoin de moyennes ou de variances cumulées. - Utilisez
expanding().apply(custom_func)pour les statistiques historiques complexes qui ne sont pas disponibles parmi les fonctions intégrées. - Utilisez
rolling(n)plutôt que expanding lorsque seule l’historique récent doit influencer la valeur actuelle.
Vérification rapide
Vérifiez votre compréhension des fenêtres extensibles présentées dans cette leçon.
Récapitulatif de la leçon
Dans cette leçon, vous avez appris que expanding() calcule des statistiques cumulées sur une fenêtre qui s’agrandit depuis le début de la Series, que cumsum/cummax/cummin sont des raccourcis optimisés pour les opérations cumulées courantes, et que les fenêtres extensibles sont idéales pour les records historiques, les indicateurs YTD et les rendements cumulés des investissements. Nous allons maintenant étudier les moyennes mobiles pondérées exponentiellement (EWMA), qui accordent davantage de poids aux observations récentes.
Apprends Python avec un tuteur IA — gratuit
Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.
- Cours
- 30
- Leçons
- 120
Questions Fréquemment Posées
La leçon « Fenêtres cumulées » est-elle gratuite ?
Oui — le texte complet de « Fenêtres cumulées » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Pandas & NumPy Academy, passe à CoddyKit PRO. Le cours Pandas & NumPy Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Fenêtres cumulées » ?
Calculez des statistiques cumulées incluant toutes les lignes depuis le début jusqu’à chaque point avec expanding().sum(). Tu pratiques Pandas & NumPy Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Pandas & NumPy Academy ?
Aucune expérience préalable n'est requise. Pandas & NumPy Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Fenêtres cumulées » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Pandas & NumPy Academy ?
Oui. Chaque leçon Pandas & NumPy Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Fenêtres glissantes
- Fenêtres cumulées
- Moyenne mobile pondérée exponentiellement
- Rangs et percentiles au sein des groupes