A time series analysis and Bayesian forecasting project on historical Paris temperature data, exploring long-term trends, seasonality, and producing probabilistic 12-month temperature forecasts with quantified uncertainty.
This notebook analyzes daily/monthly historical temperature records for Paris to understand long-term warming trends and seasonal cycles, then builds a custom Bayesian regression model (trend + seasonality + lag-12 dependence) to forecast future average daytime temperatures, complete with credible intervals.
Source file: paris-historical-temperature.csv
| Column | Description |
|---|---|
observ_date |
Date of observation |
avg_day |
Average daytime temperature (target variable) |
avg_night |
Average nighttime temperature |
max_day |
Maximum daytime temperature |
max_night |
Maximum nighttime temperature |
- Observations: 1,462
- Time unit: Monthly
- Chosen because it's a chronologically ordered, regularly-spaced series well suited to trend/seasonality decomposition, ACF/PACF analysis, stationarity testing, and Bayesian modeling of temperature as a probabilistic variable.
- Parses
observ_dateto datetime, sorts chronologically, and sets it as the index. - Checks for missing values, duplicate rows, and time-interval consistency.
- Detects and removes outliers in
avg_dayusing the IQR method, then interpolates the gaps. - Engineers features:
lag_1,lag_12(same month, prior year),month,year.
- Plots the raw time series and observes a strong yearly seasonal cycle with a slight long-term upward trend.
- Runs an additive seasonal decomposition (period = 12) to separate trend, seasonal, and residual components.
- Examines ACF/PACF plots — strong seasonal correlation at lags 12/24/36 and early-lag autoregressive structure, supporting an AR/seasonal modeling approach.
- Flags extreme values (±2 standard deviations) as likely unusual weather events or measurement anomalies.
Builds a custom Bayesian regression model (using PyMC) with the structure:
avg_day(t) = α + β·t + γ₁·sin(2πt/12) + γ₂·cos(2πt/12) + φ·avg_day(t−12) + ε
| Term | Meaning |
|---|---|
alpha |
Baseline temperature level |
beta |
Long-term monthly trend |
gamma1, gamma2 |
Strength/phase of the yearly seasonal cycle |
phi |
Dependence on the same month in the previous year |
sigma |
Unexplained variability |
- Fit via MCMC sampling (
pm.sample, 2000 draws, 1000 tuning steps,target_accept=0.95). - Diagnosed with
arvizsummary tables and trace plots. - In-sample fitted values are compared against observed data to check model fit.
- Projects 12 months ahead using posterior mean parameter estimates, feeding forecasts back in for the lag-12 term.
- Performs an out-of-sample backtest: trains on all but the last 24 months, forecasts that held-out period using posterior samples, and plots the forecast mean with a 95% credible interval against actual values.
- Evaluates forecast accuracy with MAE and RMSE.
- The series is dominated by strong, consistent yearly seasonality and a gradual warming trend, making it non-stationary in its raw form.
- The Bayesian model captures both the seasonal cycle and trend well, with in-sample fitted values closely tracking observed temperatures.
- Backtested forecasts track actual held-out temperatures closely, preserving the seasonal pattern and trend.
- Unlike traditional point-forecast models, the Bayesian approach provides credible intervals that quantify forecast uncertainty.
- Python 3.x
- Packages:
pandas numpy matplotlib statsmodels pymc arviz scikit-learn
Install with:
pip install pandas numpy matplotlib statsmodels pymc arviz scikit-learn- Place
paris-historical-temperature.csvin the same directory as the notebook (semicolon-delimited). - Open and run
ParisWeather.ipynbcell by cell. - Note that the Bayesian model fitting cells (MCMC sampling) can take several minutes depending on your hardware.
- Review the plots (time series, decomposition, ACF/PACF, outliers, fitted vs. observed, forecasts) and printed model summaries / error metrics as you go.
- The forecasting section refits the Bayesian model on a train/test split (holding out the last 24 months) purely for backtesting; the standalone 12-month forecast earlier in the notebook uses the model fit on the full dataset.
- The lag-12 term means forecasts beyond the first 12 months would need previously forecasted values as inputs, which can compound uncertainty over longer horizons.