The world’s leading publication for data science, AI, and ML professionals.

3 Types of Seasonality and How to Detect Them

Understanding time series seasonality

Photo by insung yoon on Unsplash
Photo by insung yoon on Unsplash

Analyzing and dealing with Seasonality is a key exercise in time series analysis.

In this article, we’ll describe three types of seasonality and how to detect them.


What is seasonality?

Seasonality is one of the key components that make up a time series. Seasonality refers to systematic movements that repeat over a given period with a similar intensity.

Seasonal variations can be caused by various factors, such as weather, calendar, or economic conditions. Examples abound in various applications. Flights are more expensive in the summer because of vacations and tourism. Another example is consumer spending which increases in December due to holidays.

Seasonality means the average value in some periods will be different than the average value at other times. This issue causes the series to be non-stationary. This is why it is important to analyze seasonality when building a model.


Three Types of Seasonality

There are three types of seasonal patterns that can emerge in time series. Seasonality can be deterministic or stochastic. On the stochastic side, seasonal patterns can be either stationary or not.

These types of seasonality are not mutually exclusive. A time series can have both a deterministic and stochastic seasonal component.

Let’s describe each pattern in turn.

Deterministic seasonality

Time series with a deterministic seasonality have a constant seasonal pattern. It always recurs in a predictable way, both in intensity and periodicity:

  • similar intensity: the level of the seasonal pattern stays the same over the same seasonal period;
  • unchanged periodicity: the location of the peaks and troughs does not change. In other words, the time between each repetition of the seasonal pattern is constant.

Here’s a synthetic monthly time series with a deterministic seasonality:

import numpy as np

period = 12
size = 120
beta1 = 0.3
beta2 = 0.6
sin1 = np.asarray([np.sin(2 * np.pi * i / 12) for i in np.arange(1, size + 1)])
cos1 = np.asarray([np.cos(2 * np.pi * i / 12) for i in np.arange(1, size + 1)])

xt = np.cumsum(np.random.normal(scale=0.1, size=size))

series_det = xt + beta1*sin1 + beta2*cos1 + np.random.normal(scale=0.1, size=size)
An artificial monthly series and its deterministic seasonal component. Image by author.
An artificial monthly series and its deterministic seasonal component. Image by author.

This time series is adapted from the book in reference [3].

Constant seasonality can be well handled by seasonal dummy explanatory variables. A categorical variable that describes the seasonal period. In this case, the month that corresponds to each time step. This categorical variable is transformed into a set of indicator (dummy) variables by one-hot encoding.

You can also use Fourier series to model seasonality. Fourier series are sine and cosine waves with varying periods. You can learn more about these in a previous article.

Stochastic stationary seasonality

beta1 = np.linspace(-.6, .3, num=size)
beta2 = np.linspace(.6, -.3, num=size)
sin1 = np.asarray([np.sin(2 * np.pi * i / 12) for i in np.arange(1, size + 1)])
cos1 = np.asarray([np.cos(2 * np.pi * i / 12) for i in np.arange(1, size + 1)])

xt = np.cumsum(np.random.normal(scale=0.1, size=size))

# synthetic series with stochastic seasonality
series_stoc = xt + beta1*sin1 + beta2*cos1 + np.random.normal(scale=0.1, size=size)
An artificial monthly series with a stochastic stationary seasonal component. Image by author.
An artificial monthly series with a stochastic stationary seasonal component. Image by author.

A stochastic stationary seasonality evolves over consecutive seasonal periods (e.g. year over year). The intensity is less predictable, but the periodicity stays roughly the same.

With deterministic seasonality, the best prediction for a given month doesn’t change irrespective of the year. For a stochastic stationary seasonality, the best guess depends on the value of the same month from the previous year.

Stochastic non-stationary seasonality

Sometimes, seasonal patterns change significantly over several seasonal periods. These changes can be caused by seasonal unit roots, which means that seasonality is integrated.

Besides the intensity, the periodicity of this type of seasonality also tends to change over time. This means that the peaks and troughs vary in their location.

Examples of this type of seasonal pattern appear in different domains. These include consumption series or industrial production data.

Changes are difficult to predict when time series have an integrated seasonality. Shocks cause permanent changes in the data, leading to scenarios where "spring becomes summer" – quote from reference [1].


Tests for seasonal time series

Visualizing the time series is a simple way of checking the seasonal patterns. But, there are several tests that you can use for a more systematic approach.

Measuring seasonal strength

We can quantify the strength of seasonal patterns according to the following heuristic:

import pandas as pd
from statsmodels.tsa.api import STL

def seasonal_strength(series: pd.Series) -> float:
    # time series decomposition
    series_decomp = STL(series, period=period).fit()

    # variance of residuals + seasonality
    resid_seas_var = (series_decomp.resid + series_decomp.seasonal).var()
    # variance of residuals
    resid_var = series_decomp.resid.var()

    # seasonal strength
    result = 1 - (resid_var / resid_seas_var)

    return result

This function estimates the strength of seasonality, irrespective of whether it is deterministic or stochastic.

# strong seasonality in the deterministic series
seasonal_strength(series_det)
# 0.93

# strong seasonality in the stochastic series
seasonal_strength(series_stoc)
# 0.91

The authors of this metric recommend applying a seasonal differencing filter if the value is above 0.64 [2].

An alternative to detect seasonality is the QS test, which checks the auto-correlations at seasonal lags.

Detecting non-stationary seasonality

There are a few statistical tests designed to check whether the seasonal pattern is non-stationary.

A common example is the Canova-Hansen (CH) test. Its hypotheses are the following:

  • H0 (null hypothesis): The seasonal pattern is stationary (no seasonal unit root);
  • H1: The series contains a seasonal unit root

The OCSB test and the HEGY test are two alternatives to CH.

These are implemented in the function nsdiffs, which is available in the pmdarima Python library (and in the R forecast package).

from pmdarima.arima import nsdiffs

period = 12 # monthly data

nsdiffs(x=series_det, m=period, test='ch')
nsdiffs(x=series_det, m=period, test='ocsb')

nsdiffs(x=series_stoc, m=period, test='ch')
nsdiffs(x=series_stoc, m=period, test='ocsb')

The function nsdiffs returns the number of seasonal differencing steps required to make the series stationary.

In this case, the result is 0 for all four cases. But, as we’ve seen above, it does not mean that the seasonal pattern is not strong.

Related tests

There are other tests specially designed for seasonal data. For example, the seasonal Kendall test is a nonparametric test that checks seasonal time series for monotonic trends.


Key Takeaways

  • The seasonal component of a time series is a systematic pattern that repeats over a given period.
  • Seasonality can be deterministic, stochastic, or a mix of both. Stochastic seasonal patterns may or may not be stationary
  • You can estimate seasonal strength or use statistical tests (e.g QS test) to detect seasonality
  • Seasonal unit roots can also be identified with statistical tests. The function nsdiffs estimates whether seasonal differencing is required for stationarity.

Thank you for reading and see you in the next story!


Related Articles

Code

References

[1] Canova, F. and Hansen, Bruce E. (1995) "Are seasonal patterns constant over time? A test for seasonal stability". Journal of Business & Economic Statistics, 13(3), pp. 237–252

[2] Wang, X, Smith, KA, Hyndman, RJ (2006) "Characteristic-based clustering for time series data", Data Mining and Knowledge Discovery, 13(3), 335–364.

[3] Holmes, Elizabeth E., Mark D. Scheuerell, and E. J. Ward. "Applied Time Series Analysis for fisheries and environmental data." NOAA Fisheries, Northwest Fisheries Science Center, Seattle, WA (2020).

[4] Time-series: deterministic/stochastic seasonality, in "The Samuelson Condition"


Related Articles