04 — Foundations

Differencing#

FoundationsStatistical 1 min read
◆ The PatternThe simplest way to make a series stationary

Differencing subtracts the previous observation from the current one: Δyt = yt − yt−1. This removes trends. Second differencing removes quadratic trends. Seasonal differencing (yt − yt−m) removes periodic patterns.

Δyt = yt − yt−1   |   Δ2yt = Δyt − Δyt−1   |   Δmyt = yt − yt−m
The d parameter in ARIMA(p,d,q) is the number of regular differences needed for stationarity.
// Interactive — differencing levels
Differences (d)0
Don’t over-difference: Each difference removes one degree of integration. If the series is already stationary, differencing adds artificial noise. Check with ADF after each step.
Pattern bridge: Differencing converts levels to returns — exactly what candlestick charts show. In ML, the concept parallels gradient computation: the rate of change matters more than the absolute value.
Worked example

A series with a trend of 0.3 per step: its first difference has mean 0.298 and no trend left. But differencing a series that was already stationary does harm: white noise, differenced, gets a lag-1 autocorrelation of −0.49 (theory: −0.5) and 1.98× the variance. Over-differencing invents structure and adds noise.

Where it misleads
  • Check whether differencing is needed (KPSS, ADF, the ACF) rather than differencing by habit.
  • A deterministic trend is better modelled as a trend; differencing it creates a non-invertible MA term.
  • Seasonal and ordinary differencing together can over-difference quickly; one seasonal difference is often enough.
In code
rng = np.random.default_rng(3)
t = np.arange(500)
trend = 0.3 * t + rng.normal(0, 1, 500)
d1 = np.diff(trend)
noise = rng.normal(0, 1, 500)                    # already stationary
over = np.diff(noise)                            # differenced anyway

def acf1(x):
    x = x - x.mean(); return (x[:-1] * x[1:]).sum() / (x * x).sum()
Python, in your browser — edit the code and run it again

Assumes import numpy as np and import pandas as pd. Each snippet simulates or makes up its own series, as the comments say.

The same idea with a library
# Python — differencing
import pandas as pd

diff1 = series.diff().dropna()         # first difference
diff2 = series.diff().diff().dropna()   # second difference
sdiff = series.diff(12).dropna()        # seasonal difference (m=12)
Sources
  • Time Series Analysis: Forecasting and Control (5th ed.), G. E. P. Box, G. M. Jenkins, G. C. Reinsel & G. M. Ljung, Wiley, 2015
  • D. Kwiatkowski, P. C. B. Phillips, P. Schmidt & Y. Shin, “Testing the Null Hypothesis of Stationarity against the Alternative of a Unit Root”, Journal of Econometrics 54(1–3), 1992
  • Forecasting: Principles and Practice (3rd ed.), R. J. Hyndman & G. Athanasopoulos, OTexts, 2021

Last reviewed October 2026 · How this site checks its content · Report a mistake

Check yourself

1. What do you get when you difference a random walk once?

Show answer

C. A random walk is the cumulative sum of its steps; differencing undoes the sum.

2. What does a seasonal difference at lag 12 remove from monthly data?

Show answer

C. yt − yt−12 compares each month with the same month a year earlier, cancelling a repeating seasonal shape.

3. What happens if you difference a series that was already stationary?

Show answer

B. Over-differenced series show a lag-1 autocorrelation near −0.5 and larger forecast variance.

Linked from 1
← Previous
Decomposition
Open in the full reader, with the topic sidebar