Quando il Calendario non Basta Più
C’è un momento preciso in cui ogni responsabile della logistica smette di credere nei miracoli della “media storica”: è quella mattina di gennaio in cui il magazzino è deserto, i camion sono bloccati dal nevischio e i costi fissi continuano a correre come se nulla fosse.
Affidarsi solo al “abbiamo sempre fatto così” o alle semplici ricorrenze stagionali oggi non è solo rischioso, è pigrizia operativa. Il mondo reale è sporco, caotico e influenzato da variabili che non si trovano su un calendario: il meteo, il prezzo del gasolio, uno sciopero improvviso o una promozione lampo su Amazon.
In questo approfondimento usciamo dalla teoria ed entriamo nel vivo della Business Intelligence Predittiva, sporcandoci le mani con Python per capire come i dati esterni possano trasformare una previsione mediocre in un vantaggio competitivo da centinaia di migliaia di euro.
Forecasting con Prophet
📘 Facebook Prophet: guida completa al forecasting di serie temporali
📘 Previsione carichi logistica con Python e Prophet: tutorial pratico
📘 Previsioni di vendita con Facebook Prophet: 4 esercizi progressivi
Esercizio Avanzato: Previsione Logistica con Regressori Esterni (Meteo)
Scenario
Il fornitore “LogisticaCelere” ha notato che i volumi non dipendono solo dal giorno della settimana o dalle feste, ma anche dalle condizioni climatiche. Pioggia forte e neve rallentano le operazioni e riducono i carichi gestibili. Il tuo compito è costruire un modello che “impari” questa relazione.
Passo 1 – Simulazione dei file CSV
Per prima cosa, generiamo i dati. Creeremo un set di addestramento (tutto il 2023) e un set di previsioni meteo (la prima settimana del 2024).
import pandas as pd
import numpy as np
# Setup per dati riproducibili
np.random.seed(42)
date_range = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
# 1. Generazione Meteo: molti giorni di sole (0mm) e alcuni di pioggia
pioggia = np.random.exponential(scale=2, size=len(date_range))
pioggia = np.where(pioggia < 1.8, 0, pioggia)
# 2. Generazione Carichi (y): Base 5000 + effetto pioggia (-150 colli per ogni mm)
y = 5000 + (np.random.normal(0, 100, len(date_range))) + (pioggia * -150)
df_storico = pd.DataFrame({'ds': date_range, 'y': y.astype(int), 'pioggia_mm': np.round(pioggia, 1)})
df_storico.to_csv('carichi_meteo_storico.csv', index=False)
# 3. Generazione Previsioni Meteo Future (7 giorni del 2024)
date_future = pd.date_range(start='2024-01-01', periods=7, freq='D')
# Simuliamo un forte temporale il 3 Gennaio (15mm)
previsioni_meteo = [0, 0, 15.0, 2.0, 0, 0, 0]
df_meteo_futuro = pd.DataFrame({'ds': date_future, 'pioggia_mm': previsioni_meteo})
df_meteo_futuro.to_csv('previsioni_meteo_prossima_settimana.csv', index=False)
print("✅ File CSV generati: 'carichi_meteo_storico.csv' e 'previsioni_meteo_prossima_settimana.csv'")
File 'carichi_meteo_storico.csv' generato con successo!
ds y pioggia_mm
0 2023-01-01 5343 0.0
1 2023-01-02 4086 6.0
2 2023-01-03 4606 2.6
3 2023-01-04 4846 1.8
4 2023-01-05 5238 0.0
File 'carichi_meteo_storico.csv' generato con successo!
ds y pioggia_mm
0 2023-01-01 5343 0.0
1 2023-01-02 4086 6.0
2 2023-01-03 4606 2.6
3 2023-01-04 4846 1.8
4 2023-01-05 5238 0.0
Passo 2 – Configurazione del Modello con Regressore
In Prophet, una variabile esterna si chiama add_regressor. È fondamentale aggiungerla prima di lanciare il comando .fit().
from prophet import Prophet
# Carichiamo i dati
df = pd.read_csv('carichi_meteo_storico.csv')
df['ds'] = pd.to_datetime(df['ds'])
# Inizializziamo il modello
# Nota: qui potresti aggiungere anche le 'holidays' come negli esercizi precedenti
m = Prophet(yearly_seasonality=True, daily_seasonality=False)
# AGGIUNTA DEL REGRESSORE: diciamo al modello di imparare dalla colonna 'pioggia_mm'
m.add_regressor('pioggia_mm', mode='additive')
# Addestramento
m.fit(df)
print("🧠 Il modello ha imparato la relazione tra pioggia e carichi.")
🧠 Il modello ha imparato la relazione tra pioggia e carichi.
Passo 3 – Previsione e Integrazione Dati Futuri
Per prevedere il futuro con un regressore, il dataframe future deve contenere i valori previsti di quella variabile (in questo caso, le previsioni del tempo).
# 1. Creiamo il dataframe futuro per 7 giorni
future = m.make_future_dataframe(periods=7)
# 2. Carichiamo le previsioni meteo e uniamole al dataframe futuro
df_meteo_futuro = pd.read_csv('previsioni_meteo_prossima_settimana.csv')
df_meteo_futuro['ds'] = pd.to_datetime(df_meteo_futuro['ds'])
# Uniamo i dati: Prophet ha bisogno della colonna 'pioggia_mm' anche nel futuro
future = pd.merge(future, df_meteo_futuro, on='ds', how='left').fillna(0)
# 3. Predizione
forecast = m.predict(future)
Passo 4 – Analisi dell’Impatto (Componenti)
Vediamo graficamente quanto la pioggia ha pesato sulle nostre previsioni.
import matplotlib.pyplot as plt
# Visualizzazione dei componenti
fig = m.plot_components(forecast)
plt.show()
# Focus sulla settimana di Gennaio 2024
gennaio_2024 = forecast[forecast['ds'] >= '2024-01-01']
print("\nPrevisioni Gennaio 2024:")
print(gennaio_2024[['ds', 'yhat', 'pioggia_mm']].to_string(index=False))
Per dimostrare il valore di un modello al management, non bastano i grafici: servono i numeri e, possibilmente, il loro impatto economico.
In questa fase finale, confronteremo il MAE (Mean Absolute Error) dei due modelli. Il MAE ci dice, in media, di quanti colli “sbagliamo” la previsione ogni giorno.
Le Metriche di Valutazione: Misurare l’Affidabilità
Per confrontare la bontà dei nostri modelli (Base vs con Regressori) e capire quanto possiamo fidarci delle previsioni, utilizzeremo due indicatori statistici fondamentali.
1. MAE (Mean Absolute Error)
Rappresenta l’errore medio espresso in unità assolute (nel nostro caso, il numero di colli).
$$MAE = \frac{1}{n} \sum_{i=1}^{n} |y_i – \hat{y}_i|$$
Utile per: Capire l’impatto fisico dell’errore sulla gestione del magazzino e dei mezzi.
2. MAPE (Mean Absolute Percentage Error)
Esprime l’errore in termini percentuali, permettendo di capire il “peso” dello scostamento rispetto al volume totale.
$$MAPE = \frac{100\%}{n} \sum_{i=1}^{n} \left| \frac{y_i – \hat{y}_i}{y_i} \right|$$
Utile per: Confrontare l’accuratezza su periodi con volumi di traffico molto diversi (es. alta vs bassa stagione).
Interpretazione Pratica
In un contesto di logistica reale:
- Un MAE di 50 significa che, in media, la nostra previsione “sbaglia” di 50 colli ogni giorno.
- Un MAPE del 5% ci dice che il nostro errore è molto contenuto e che il modello è estremamente affidabile per la pianificazione operativa.
Script Completo: Dalla Simulazione al Risparmio Economico
Copia ed esegui questa cella per avere il confronto finale:
import pandas as pd
import numpy as np
from prophet import Prophet
from sklearn.metrics import mean_absolute_error
import matplotlib.pyplot as plt
# --- 1. GENERAZIONE DATI (Simulazione) ---
np.random.seed(42)
date_range = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
pioggia = np.random.exponential(scale=2, size=len(date_range))
pioggia = np.where(pioggia < 1.8, 0, pioggia)
# Carichi influenzati dalla pioggia (-150 colli per mm)
y = 5000 + (np.random.normal(0, 100, len(date_range))) + (pioggia * -150)
df = pd.DataFrame({'ds': date_range, 'y': y.astype(int), 'pioggia_mm': np.round(pioggia, 1)})
# --- 2. ADDESTRAMENTO MODELLO BASE (Senza Meteo) ---
m_base = Prophet()
m_base.fit(df[['ds', 'y']]) # Usa solo data e carichi
forecast_base = m_base.predict(df[['ds']])
# --- 3. ADDESTRAMENTO MODELLO METEO (Avanzato) ---
m_meteo = Prophet()
m_meteo.add_regressor('pioggia_mm')
m_meteo.fit(df) # Usa data, carichi e pioggia
forecast_meteo = m_meteo.predict(df)
# --- 4. CONFRONTO NUMERICO ---
# Calcoliamo il MAE (Mean Absolute Error)
mae_base = mean_absolute_error(df['y'], forecast_base['yhat'])
mae_meteo = mean_absolute_error(df['y'], forecast_meteo['yhat'])
# Calcolo del risparmio economico stimato
# Ipotizziamo che ogni errore di 1 collo costi all'azienda 2.50€
costo_per_errore = 2.50
risparmio_giornaliero = (mae_base - mae_meteo) * costo_per_errore
risparmio_annuo = risparmio_giornaliero * 365
# --- 5. OUTPUT DEI RISULTATI ---
print("="*40)
print("REPORT DI PREVISIONE LOGISTICA")
print("="*40)
print(f"Errore Medio Modello Base: {mae_base:.1f} colli")
print(f"Errore Medio Modello Meteo: {mae_meteo:.1f} colli")
print("-"*40)
print(f"MIGLIORAMENTO ACCURATEZZA: {((mae_base - mae_meteo)/mae_base)*100:.1f}%")
print(f"RISPARMIO ECONOMICO STIMATO: €{risparmio_annuo:,.2f} / anno")
print("="*40)
========================================
REPORT DI PREVISIONE LOGISTICA
========================================
Errore Medio Modello Base: 260.9 colli
Errore Medio Modello Meteo: 77.2 colli
----------------------------------------
MIGLIORAMENTO ACCURATEZZA: 70.4%
RISPARMIO ECONOMICO STIMATO: €167,686.67 / anno
========================================
Analisi dei Risultati per il Business: Dal Dato al Valore
Perché questo calcolo non è solo un esercizio accademico ma un asset fondamentale per l’azienda? Un Data Scientist non deve solo “prevedere”, deve validare e giustificare l’impatto economico delle proprie scelte algoritmiche.
📊 Validazione Matematica
Utilizziamo il MAE poiché è la metrica più intuitiva per i non tecnici:
$$MAE = \frac{1}{n} \sum_{i=1}^{n} |y_i – \hat{y}_i|$$
In termini aziendali, il MAE rappresenta semplicemente la media dei “pacchi mancati” o dei colli sovrastimati ogni giorno.
💰 Giustificazione del Budget
Dimostrare che un modello con regressori esterni non è solo “tecnicamente superiore” ma riduce l’errore operativo del 10-15% significa tradurre la statistica in risparmio monetario. Meno personale in eccesso o meno penali per ritardi sono argomenti che garantiscono l’approvazione del management.
⚡ Riduzione della Volatilità
Il modello meteo non si limita a ridurre l’errore medio; la sua vera forza è l’eliminazione dei grandi fallimenti predittivi nei giorni di pioggia intensa. Evitare il collasso del magazzino in situazioni critiche è il primo passo per una logistica resiliente.
📌 Takeaway per il Management
L’integrazione di dati esterni (Meteo, Prezzi dei carburanti, Eventi locali) trasforma la previsione da passiva (basata solo sul calendario) a reattiva (basata sul mondo reale).
Risultato finale: Una riduzione del MAPE anche solo del 2% può tradursi in un risparmio di decine di migliaia di euro l’anno in ottimizzazione della flotta e gestione del personale.





