Regression & Prediction · Lesson 7 of 7
Time Series Regression
~14 min
The Concept
Your regression model treats each monthly observation as independent. But Bluewater River's streamflow in July is strongly correlated with its streamflow in June, a wet month tends to follow a wet month. This violates one of linear regression's core assumptions: that residuals are uncorrelated. Ignoring this makes your standard errors wrong and your hypothesis tests unreliable.
Autocorrelation (when today's value is related to yesterday's value, instead of being a fresh independent surprise) means a time series is correlated with its own past values. If today's streamflow helps predict tomorrow's, the observations are not independent, and classical regression assumes they are. Ignoring autocorrelation causes the model to underestimate uncertainty, making results look more precise than they really are.
The autocorrelation function (ACF) measures the correlation between a series and lagged versions of itself. A spike at lag 1 means consecutive observations are correlated; a spike at lag 12 means the same month in different years are correlated (seasonal autocorrelation).
The Analogy
It is like counting today's weather and yesterday's weather as two completely separate, independent pieces of evidence, when really a hot day is much more likely to follow another hot day. Treating connected days as if they were unrelated coin flips makes your conclusions look more certain than they really are.
Code (optional)
import numpy as np
import pandas as pd
from statsmodels.stats.stattools import durbin_watson
from statsmodels.graphics.tsaplots import plot_acf
import matplotlib.pyplot as plt
streamflow = np.load("bluewater_monthly_streamflow.npy")
residuals = np.load("regression_residuals.npy")
# Durbin-Watson test: values near 2 = no autocorrelation
# values near 0 = positive autocorrelation
# values near 4 = negative autocorrelation
dw = durbin_watson(residuals)
print(f"Durbin-Watson statistic: {dw:.3f}")
if dw < 1.5:
print("Warning: positive autocorrelation in residuals detected")
# Plot ACF of residuals
fig, ax = plt.subplots(figsize=(8, 4))
plot_acf(residuals, ax=ax, lags=24)
plt.savefig("acf_residuals.png")Line by line
- We check the residuals (not the raw data) for autocorrelation, it's only in the residuals that assumption violations matter.
- durbin_watson() gives a simple test statistic; values far from 2 indicate autocorrelated residuals.
- plot_acf() shows which lags are significant, a spike at lag 12 in monthly residuals would indicate unmodelled seasonality.
Why Real Researchers Care
Autocorrelated residuals are one of the most common violations in environmental regression. Monthly precipitation, temperature, and water quality data are almost always autocorrelated. Standard practice is to either (1) add lagged predictors to the model, (2) use GLS (Generalised Least Squares) with a correlation structure, or (3) use time-series specific models like ARIMA. Ignoring it produces over-optimistic p-values and confidence intervals.
Quick Check
Q1. What does a Durbin-Watson statistic of 0.8 (on a scale of 0–4) indicate about your regression residuals?
Your Goal
Your regression of nitrate on seasonal variables has autocorrelated residuals (DW = 1.1). Propose two concrete changes to the model that might reduce autocorrelation, based on what you know about Bluewater Basin's hydrology.
Hint: Think about what drives nitrate from one month to the next, accumulated rainfall, previous month's groundwater level, or seasonal land use patterns.
Teach It Back
Explain why autocorrelated residuals make a model's standard errors 'optimistic', and why this matters for any policy decision based on that model.