215. Periodogram

Estimate the power spectral density (PSD) of a time series — i.e., how much variance is at each frequency. The simplest spectrum estimator; built directly from the Fourier transform.

215.0.1. Definition

For a series with DFT (see [fourier.typ](fourier.typ)):

The periodogram is the function evaluated at the discrete frequencies . For a real-valued series, (symmetric around 0.5), so you only plot the first bins.

215.0.2. What it tells you

The area under the periodogram equals the variance of the series (Parseval’s theorem). So peaks tell you what fraction of variance is explained by each frequency.

215.0.3. Why raw periodograms are noisy

The periodogram is not consistent: even with infinite data, its variance at each frequency does not decrease. So the raw periodogram is a jagged estimate — peaks are real, but their estimated heights are noisy.

Two standard fixes:

215.0.3.1. 1. Smoothing the periodogram

Average the periodogram over a small window of nearby frequencies (a spectral window). Trades resolution for variance reduction.

with weights summing to 1 (e.g., Bartlett, Hann, Tukey windows).

215.0.3.2. 2. Welch’s method

Split the series into overlapping segments. Compute the periodogram of each segment. Average. Reduces variance at the cost of resolution; the standard implementation in scipy.signal.welch.

215.0.4. Significance test

How big does a peak need to be before we believe it?

For Gaussian white noise input, at each frequency. So a peak with has a known -value.

Rule of thumb: peaks more than 2-3× the surrounding noise floor are likely real; smaller peaks often vanish under significance testing.

215.0.5. Workflow

  1. Detrend the series (subtract a linear trend, or take first differences). Trend dominates the low-frequency spectrum and hides cycles.
  2. Apply a windowing function (Hann, Hamming) before FFT to reduce edge artifacts.
  3. Compute periodogram via FFT.
  4. Smooth (or use Welch’s method) to get a stable estimate.
  5. Plot vs frequency — log scale reveals weak peaks.
  6. Identify peaks; period = frequency.

215.0.6. Comparison to autocorrelation analysis

Periodogram and autocorrelation function (ACF) contain equivalent information (Wiener-Khinchin theorem):

A peak in the periodogram at frequency corresponds to oscillating autocorrelation at period . Use whichever is easier to read for your data:

Most time-series analyses use both.

Example: Periodogram of daily energy demand

Given: 2 years (730 days) of daily electricity demand.

Step 1 — preprocess

  • Detrend: subtract a linear regression line (removes long-term load growth).
  • Apply a Hann window: .

Step 2 — FFT and periodogram

from scipy.signal import periodogram
freq, psd = periodogram(y_detrended, fs=1.0, window='hann')
period = 1 / freq[1:]  # skip DC

Step 3 — read peaks

Suppose psd peaks at:

  • (period = 7 days) → strong weekly cycle (weekday vs weekend pattern)
  • (period = 365 days) → annual cycle (heating/cooling load)
  • (period = 3.5 days) → secondary peak; possibly mid-week vs end-of-week subdivision

Step 4 — interpret

Two clear seasonalities (weekly and annual) — confirms what you’d see in classical / STL decomposition, but reveals them quantitatively without imposing a seasonal period in advance.

Step 5 — use

  • For forecasting: include Fourier features at periods 7 and 365.
  • For decomposition: STL with two seasonal components, or MSTL.
  • For anomaly detection: a day with unusual frequency content (e.g., a power outage) shows up in the residuals after removing the dominant frequencies.

The periodogram is the diagnostic step that tells you which seasonal periods to model.