Finestre espandibili
Calcoli statistiche cumulative che includono tutte le righe dall'inizio fino a ogni punto usando expanding().sum().
Finestre espandibili è una lezione Pandas & NumPy Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Pandas & NumPy Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Pandas & NumPy Academy include 4 lezioni in totale.
Che cos'è una finestra espandibile?
Una finestra espandibile include tutte le righe dall'inizio della Series fino alla riga corrente: la finestra cresce a ogni nuova riga invece di rimanere fissa. Alla riga 0 contiene un solo valore; alla riga 5 ne contiene sei; alla riga 100 ne contiene 101. Le finestre espandibili vengono usate per calcolare statistiche cumulative che rappresentano il totale progressivo, la media progressiva o il massimo progressivo dall'inizio del dataset fino al momento corrente.
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)Il metodo expanding()
Series.expanding(min_periods=1) restituisce un oggetto Expanding. Il parametro min_periods (predefinito a 1) imposta il numero minimo di osservazioni richieste per ottenere il primo risultato non-NaN. A differenza di rolling(n), la finestra di expanding() non è fissa: inizia sempre dall'inizio. Può concatenare qualsiasi aggregazione: .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)Pandas cumsum, cumprod, cummax, cummin
Per le statistiche cumulative più comuni, Pandas fornisce metodi diretti su Series e DataFrame senza dover usare expanding(): cumsum(), cumprod(), cummax() e cummin(). Si tratta di implementazioni ottimizzate, leggermente più veloci delle equivalenti con expanding(). Usi queste scorciatoie per metriche aziendali tipiche, come i ricavi da inizio anno (cumsum) o il prezzo massimo storico (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))Calcolo da inizio anno con expanding
Un impiego classico delle finestre espandibili è il calcolo dei ricavi da inizio anno (YTD). Per ogni giorno, si desidera sommare tutti i ricavi dal 1º gennaio dell'anno corrente fino a quel giorno. Si tratta semplicemente di applicare cumsum() all'interno di ciascun gruppo annuale. Lo implementi con groupby(year).cumsum(): il cumsum viene azzerato all'inizio di ogni anno solare e continua ad accumularsi nel corso dell'anno.
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))Deviazione standard con finestra espandibile
expanding().std() calcola la deviazione standard progressiva usando tutti i dati dall'inizio fino alla riga corrente. È utile per monitorare se la variabilità di una metrica aumenta o diminuisce nel tempo, ad esempio per verificare se le vendite giornaliere di un prodotto diventano più o meno prevedibili con la maturazione dell'attività. A differenza della deviazione standard mobile, che riflette solo la variabilità recente, la deviazione standard espandibile considera l'intera dispersione storica.
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))Confronto tra rolling ed expanding
La distinzione fondamentale è la seguente: le finestre mobili riflettono le prestazioni recenti (gli ultimi n giorni) e non risentono dei dati molto lontani nel tempo, mentre le finestre espandibili includono tutta la cronologia e quindi convergono lentamente verso valori stabili. Usi rolling quando Le interessano le tendenze recenti (una media mobile su 7 giorni risponde ai cambiamenti recenti più rapidamente di una su 90 giorni). Usi expanding quando desidera statistiche storiche complessive o metriche YTD che non devono mai dimenticare i dati precedenti.
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()Expanding apply per statistiche cumulative personalizzate
expanding().apply(func) applica una funzione personalizzata a tutti i dati dall'inizio fino alla riga corrente, proprio come rolling().apply(). Ciò consente di calcolare statistiche cumulative non disponibili tra quelle integrate, ad esempio il coefficiente di variazione cumulativo (std/mean), la mediana progressiva o un indice di Sharpe cumulativo. La funzione riceve un array NumPy contenente tutti i valori osservati fino a quel momento e deve restituire uno scalare.
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))Finestre espandibili e gestione dei NaN
Per impostazione predefinita, le finestre espandibili ignorano i valori NaN: un NaN al centro della Series viene ignorato nel calcolo della somma o della media cumulativa. Può verificarlo con skipna=True (il valore predefinito nella maggior parte delle aggregazioni Pandas). Quando lavora con serie temporali che contengono valori mancanti effettivi (ad esempio, nessuna contrattazione nei fine settimana), le statistiche espandibili vengono calcolate solo sui valori non-NaN osservati fino a quel momento, che è generalmente il comportamento desiderato.
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.')Finestre espandibili per benchmark progressivi
Le finestre espandibili sono ideali per calcolare benchmark progressivi: il massimo storico, il miglior trimestre di sempre o il tasso di errore più basso dall'avvio. Questi KPI richiedono di conservare tutti i valori storici, mentre una finestra mobile dimenticherebbe i record più vecchi. L'uso di cummax() o cummin() restituisce il valore migliore (o peggiore) progressivo in ogni momento, rendendo semplice monitorare quando vengono stabiliti nuovi record.
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'))Esempio pratico: rendimenti cumulativi
In finanza, i rendimenti cumulativi mostrano quanto è cresciuto un investimento dalla data iniziale a ciascuna data successiva. A partire dai rendimenti percentuali giornalieri, il prodotto cumulativo di (1 + daily_return) fornisce il fattore di crescita totale. In questo caso, un prodotto espandibile è più naturale di un prodotto mobile: si desidera monitorare la crescita totale dall'inizio dell'investimento, non solo quella degli ultimi n giorni.
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}%')Quando usare expanding, rolling o cumsum
Linee guida per scegliere l'approccio corretto:
- Usi
cumsum() / cummax() / cummin()per semplici aggregazioni cumulative: sono l'opzione più veloce. - Usi
expanding().mean() / std()quando ha bisogno di medie o varianze cumulative progressive. - Usi
expanding().apply(custom_func)per statistiche storiche complesse non disponibili tra quelle integrate. - Usi
rolling(n)invece di expanding quando solo la cronologia recente deve influenzare il valore corrente.
Verifica rapida
Verifichi la Sua comprensione delle finestre espandibili illustrate in questa lezione.
Riepilogo della lezione
In questa lezione ha imparato che expanding() calcola statistiche cumulative su una finestra crescente dall'inizio della Series, cumsum/cummax/cummin sono scorciatoie ottimizzate per le operazioni cumulative più comuni e le finestre espandibili sono ideali per record storici, metriche YTD e rendimenti cumulativi degli investimenti. Ora esamineremo le medie mobili ponderate esponenzialmente (EWMA), che attribuiscono un peso maggiore alle osservazioni recenti.
Impara Python con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 30
- Lezioni
- 120
Domande Frequenti
La lezione «Finestre espandibili» è gratuita?
Sì — il testo completo di «Finestre espandibili» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Pandas & NumPy Academy, passa a CoddyKit PRO. Il corso Pandas & NumPy Academy include 4 lezioni in totale.
Cosa imparerò in «Finestre espandibili»?
Calcoli statistiche cumulative che includono tutte le righe dall'inizio fino a ogni punto usando expanding().sum(). Eserciti Pandas & NumPy Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Pandas & NumPy Academy?
Non è richiesta alcuna esperienza precedente. Pandas & NumPy Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Finestre espandibili»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Pandas & NumPy Academy?
Sì. Ogni lezione Pandas & NumPy Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Finestre mobili
- Finestre espandibili
- Media mobile ponderata esponenzialmente
- Ranghi e percentili all'interno dei gruppi