time series decomposition and stationarity

Time Series Decomposition and Stationarity

Companion article for Episode 86 of the Intelevo YouTube channel

Every time series looks messy at first glance. A sales chart zigzags. A temperature graph climbs, dips, and climbs again. But underneath that mess, a simple structure hides. This article breaks that structure apart, piece by piece.

We cover two ideas today: decomposition and stationarity. Together, they form the backbone of almost every classical forecasting technique. Watch the full video walkthrough on the Intelevo YouTube channel for a step-by-step explanation with visuals and live code. This article expands on that video, so you can read at your own pace and revisit the details whenever you need them.

Let’s get started.

A Quick Recap First

In the previous episode, we introduced time series data. We learned that a time series is a sequence of values recorded in order, at regular time intervals. Order matters. Shuffle the rows, and you lose the story.

We also mentioned something important: every time series secretly contains three smaller stories. These are trend, seasonality, and residual noise. We promised we would separate them eventually. Today, we keep that promise.

The Big Idea: Decomposition Is Just Un-Blending

Picture a smoothie. Once you blend fruit, ice, and juice together, you get one glass, one color, and one taste. You cannot tell just by looking that there was banana in there, or apple, or ice.

Your raw time series behaves the same way. Trend, seasonality, and noise blend into a single wiggly line. Decomposition does not add anything new to that mixture. Instead, it un-blends the line, and it separates the direction, the rhythm, and the leftover wobble that were always present.

So why bother? Because separated ingredients are far easier to understand. You can study each one on its own. Later, you can even model each one separately, which often produces better forecasts than tackling the whole tangled mess at once.

In short, decomposition is subtraction, not magic. You pull out what you already understand, and you look closely at what remains.

Meet the Three Ingredients

Every time series decomposes into three components. Let’s name them clearly, since we will use these terms constantly from here on.

Trend describes the slow, underlying direction of your data. It climbs, falls, or stays flat, once you ignore the daily wobble. Think of a company’s revenue growing steadily over five years.

Seasonality describes the pattern that repeats on a fixed clock. Ice-cream sales spike every summer. Traffic increases every Monday morning. This pattern repeats predictably, so you can plan around it.

Residual, sometimes called noise, is whatever remains after you remove trend and seasonality. No calendar explains it. No slope explains it. It is the unpredictable wobble that every real dataset carries.

Put these three pieces together, and you get a simple formula:

Original = Trend + Seasonality + Residual

That’s the entire idea, in one line.

Additive or Multiplicative: Do the Stories Add Up, or Multiply?

Before you decompose a series, you must make one small decision. Do the three components add together, or do they multiply?

In an additive model, seasonal swings stay the same size no matter how large the trend grows. The formula looks like this:

Y = Trend + Seasonality + Residual

Picture steady, flat swings that never change size, regardless of the overall level.

In a multiplicative model, seasonal swings grow as the trend grows. A bigger baseline produces a bigger wiggle. The formula changes slightly:

Y = Trend × Seasonality × Residual

Picture swings that stretch wider as the series climbs higher.

Here’s a simple test to pick the right one. Look at your plotted data. If the wiggle stays roughly the same size throughout, choose additive. If the wiggle grows alongside the trend, choose multiplicative. This single visual check saves you from guessing.

Why Decomposition Actually Matters

Some learners assume decomposition is just an academic exercise. It isn’t. Pulling a series apart is genuinely diagnostic, and it pays off in three practical ways.

First, you get cleaner forecasts. You can forecast trend and season separately, then recombine them. This approach is often simpler and steadier than wrestling with one tangled model that tries to learn everything at once.

Second, you spot the real signal faster. A sudden dip in your raw line might look alarming at first. However, once you decompose the series, that dip can turn out to be routine seasonality, not an actual business problem.

Third, decomposition helps you sanity-check your data. If your residual component still shows a visible shape after decomposition, that’s a clue. Something about your model, or your data itself, deserves a second look.

In short, decomposition is how you look before you forecast.

A New Idea: Stationarity

Now let’s shift to the second big idea of this episode: stationarity. This concept trips up many beginners, so let’s build it from an analogy first.

Most classical forecasting models want a heartbeat, not a fever chart. A stationary series behaves the same way in every stretch you examine. The average stays constant. The wobble stays constant. It doesn’t matter which window of time you pick; the statistical behavior looks the same throughout.

A non-stationary series, on the other hand, drifts. Its average keeps climbing. Its swings keep widening. Or a seasonal pattern keeps reshaping the series over time. That’s the fever chart.

Why do models care so much about this distinction? Because classic forecasting math assumes tomorrow behaves statistically like today. A drifting series quietly breaks that assumption, and the model’s forecasts suffer as a result.

So remember this simple phrase: stationary means boring, in a good way. Its statistical personality doesn’t change over time, and that consistency is exactly what most models need.

Three Signs of a Stationary Series

You don’t need forty checks to confirm stationarity. You only need three.

  1. Constant mean. The average value doesn’t drift up or down as you slide your observation window through time.
  2. Constant variance. The size of the ups and downs stays roughly the same. There’s no widening funnel shape as time progresses.
  3. No leftover trend or season. No slow climb remains. No repeating calendar pattern is quietly doing the driving.

If all three conditions hold, your series is, roughly speaking, stationary. Keep these three checks in your back pocket. They will save you time on every new dataset you encounter.

Why This Matters for the Models You’ll Build Next

Here’s the connection that ties everything together. Classical models like ARIMA, which we will cover properly in the next episode, rely entirely on one assumption: a series’ statistical behavior stays consistent across time.

Feed a model like that a drifting, non-stationary series, and its forecasts drift too. Worse, those forecasts become confidently wrong the further out you project them. That combination is dangerous, since a wrong forecast that looks confident is harder to catch than an obviously shaky one.

The good news is simple. You don’t need a brand-new model to fix this problem. You just need to calm the series down first, and that’s exactly the skill we cover next. Stationarity isn’t a bureaucratic formality. It’s the permission slip most forecasting models need before they will behave properly.

How to Check for Stationarity

So, how do you actually check whether your series is stationary? Start with your eyes, and then confirm your intuition with a formal test.

Step one: the eyeball check. Plot your data. A flat, evenly-wobbling line usually looks stationary. A climbing or widening line usually isn’t. This visual scan takes seconds, and it builds your intuition fast.

Step two: the formal test. Run the Augmented Dickey-Fuller test, often shortened to the ADF test. This test returns a p-value. If that p-value falls below roughly 0.05, you can treat the series as stationary.

Don’t worry, you’re not doing calculus here. You’re simply reading one number that a Python library calculates for you. Plot first, and then test second. The test just confirms what your eyes already suspected.

The Math Behind the Fix: Differencing

Now let’s look at the one formula you genuinely need today. Thankfully, it’s just subtraction.

Y′ₜ = Yₜ − Yₜ₋₁

Let’s break each piece down individually.

  • Yₜ is the actual value observed right now. Think today’s sales figure, or today’s sensor reading.
  • Yₜ₋₁ is the value observed one step earlier. Think yesterday’s sales figure, or yesterday’s reading.
  • Y′ₜ is the differenced value. It captures how much things changed, and it removes the drifting average in the process.

That’s genuinely the whole idea. Subtract yesterday’s value from today’s value, and the drift usually disappears. You won’t need calculus, and you won’t need an advanced statistics background either.

Seeing Decomposition in Code

Theory only takes you so far. Let’s put decomposition into action using Python. We’ll use the popular statsmodels library, since it handles the heavy lifting for us.

from statsmodels.tsa.seasonal import seasonal_decompose

result = seasonal_decompose(
    df["sales"], model="additive", period=7
)
result.plot()

print(result.trend.tail())
print(result.seasonal.tail())

Let’s walk through what each line accomplishes.

First, seasonal_decompose does the entire un-blending job for you. It extracts trend, seasonal, and residual components in a single function call. You don’t need to write that logic yourself.

Next, notice the model="additive" argument. This setting tells the function that the swings stay a constant size. If your swings actually grow with the trend, switch this argument to "multiplicative" instead.

Then, the period=7 argument tells the function that the clock repeats weekly. Since our example uses daily data, seven days makes sense. For monthly data, you would use twelve. For hourly data, you would use twenty-four.

Finally, calling result.plot() produces the four-panel visual breakdown: the original series, the trend, the seasonal component, and the residual. Printing result.trend and result.seasonal lets you inspect the actual numeric values behind those plots.

One function call replaces the entire smoothie-unblending story we discussed earlier. That’s the power of a well-built library.

Testing and Fixing Stationarity in Code

Next, let’s test our series for stationarity, and then fix it if needed. Again, this only takes a few lines.

from statsmodels.tsa.stattools import adfuller

result = adfuller(df["sales"])
print("p-value:", result[1])

df["sales_diff"] = df["sales"].diff().dropna()
print("after diff:", adfuller(df["sales_diff"])[1])

Here’s the breakdown. The adfuller function runs the ADF test we discussed earlier, and it hands back a p-value as the second item in its result. That’s why we access result[1].

If that p-value sits above 0.05, your series probably isn’t stationary yet. So, we create a new column called sales_diff. We build it using .diff() followed by .dropna(). This single line applies our subtraction formula, Y′ₜ = Yₜ − Yₜ₋₁, to every row in the dataset.

Finally, we run adfuller again on the differenced series to confirm the fix worked. In short: test, difference, and test again. Most drifting series settle down after just one round of differencing.

Three Habits That Quietly Mislead

Before we wrap up, let’s address three habits that trip up even experienced practitioners.

First, trusting one glance. A short window of data can look flat purely by accident. Always check the mean and variance across several separate stretches of your dataset, not just one plot.

Second, differencing forever. One round of differencing fixes most drift problems. However, differencing again and again usually adds noise rather than removing it. Resist the urge to over-difference your data.

Third, ignoring the season. A strongly seasonal series can actually pass a naive stationarity check, yet still need seasonal differencing before you model it properly. Don’t skip this consideration just because your basic ADF test passed.

Remember, a passing p-value is a green light, not a guarantee. Always pair your statistical test with a visual plot before you commit to a modeling decision.

Key Takeaways: Four Ideas, Not Forty

Let’s consolidate everything into four memorable points.

  1. Every time series is really three stories blended together: trend, seasonality, and residual.
  2. Decomposition doesn’t invent anything new. Instead, it separates what was already there, either additively or multiplicatively.
  3. Stationary means a series’ average and spread stay steady over time. Most classic forecasting models quietly assume this property holds true.
  4. Check with your eyes first, confirm with the ADF test second, and calm any drift with one round of differencing.

Hold onto these four ideas. Decomposition and stationarity will never feel intimidating again.

What’s Coming Next

You now know how to split a series into trend, season, and residual. You also know how to calm a drifting series into a stationary one. In Episode 87, we hand that calm, stationary series to a model built specifically to read it: ARIMA, along with its seasonal sibling, SARIMA.

If today’s explanation helped clarify these concepts, watch the full video breakdown on the Intelevo YouTube channel. The video walks through every visual, every plot, and every line of code in real time, which makes these ideas even easier to absorb.

Please like the video, subscribe to the channel, and share it with anyone who might benefit. Your comments genuinely help shape future episodes, so leave your questions and feedback there. See you in Episode 87.

Leave a Comment

Your email address will not be published. Required fields are marked *