Time Series Forecasting Made Easy (Part 1): Decomposition and Baseline Models

-

I to avoid time series evaluation. Each time I took a web based course, I’d see a module titled with subtopics like Fourier Transforms, autocorrelation functions and other intimidating terms. I don’t know why, but I at all times found a reason to avoid it.

But here’s what I’ve learned: any complex topic becomes manageable after we start from the fundamentals and concentrate on understanding the intuition behind it. That’s exactly what this blog series is about : making time series feel less like a maze and more like a conversation along with your data over time.

We understand complex topics rather more easily once they’re explained through real-world examples. That’s exactly how I’ll approach this series.

In each post, we’ll work with a straightforward dataset and explore what’s needed from a time series perspective. We’ll construct intuition around each concept, understand why it matters, and implement it step-by-step on the information.

Time Series Evaluation is the means of understanding, modeling and Forecasting data that’s observed over time. It involves identifying patterns comparable to trends, seasonality and noise using past observations to make informed predictions about future values.

Let’s start by considering a dataset named Each day Minimum Temperatures in Melbourne (). This dataset comprises day by day records of the bottom temperature (in Celsius) observed in Melbourne, Australia, over a 10-year period from 1981 to 1990. Each entry includes just two columns:

Date: The calendar day (from 1981-01-01 to 1990-12-31)
Temp: The minimum temperature recorded on that day

You’ve probably heard of models like ARIMA, SARIMA or Exponential Smoothing. But before we go there, it’s a superb idea to check out some easy baseline models first, to see how well a basic approach performs on our data.

While there are various forms of baseline models utilized in time series forecasting, here we’ll concentrate on the three most essential ones, that are easy, effective, and widely applicable across industries.

Naive Forecast: Assumes the following value will probably be the identical because the last observed one.
Seasonal Naive Forecast: Assumes the worth will repeat from the identical point last season (e.g., last week or last month).
Moving Average: Takes the typical of the last points.

You is perhaps wondering, why use baseline models in any respect? Why not only go straight to the well-known forecasting methods like ARIMA or SARIMA?

Let’s consider a store owner who desires to forecast next month’s sales. By applying a moving average baseline model, they will estimate next month’s sales because the average of previous months. This straightforward approach might already deliver around 80% accuracy — adequate for planning and inventory decisions.

Now, if we switch to a more advanced model like ARIMA or SARIMA, we would increase accuracy to around 85%. But the important thing query is: is that extra 5% definitely worth the additional time, effort and resources? On this case, the baseline model does the job.

In truth, in most on a regular basis business scenarios, baseline models are sufficient. We typically turn to classical models like ARIMA or SARIMA in high-impact industries comparable to finance or energy, where even a small improvement in accuracy can have a major financial or operational impact. Even then, a baseline model is frequently applied first — not only to supply quick insights but additionally to act as a benchmark that more complex models must outperform.

Okay, now that we’re able to implement some baseline models, there’s one key thing we want to grasp first:
Each time series is made up of three essential components — trend, seasonality and residuals.

Time series decomposition separates data into trend, seasonality and residuals (noise), helping us uncover the true patterns beneath the surface. This understanding guides the alternative of forecasting models and improves accuracy. It’s also a significant first step before constructing each easy and advanced forecasting solutions.

Trend
That is the general direction your data is moving in over time — going up, down or staying flat.
Example: Regular decrease in monthly cigarette sales.

Seasonality
These are the patterns that repeat at regular intervals — day by day, weekly, monthly or yearly.
Example: Cool drinks sales in summer.

Residuals (Noise)
That is the random “leftover” a part of the information, the unpredictable ups and downs that may’t be explained by trend or seasonality.
Example: A one-time automotive purchase showing up in your monthly expense pattern.

Now that we understand the important thing components of a time series, let’s put that into practice using an actual dataset: Each day Minimum Temperatures in Melbourne, Australia.

We’ll use Python to decompose the time series into its trend, seasonality, and residual components so we are able to higher understand its structure and select an appropriate baseline model.

:

import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose

# Load the dataset
df = pd.read_csv("minimum day by day temperatures data.csv")

# Convert 'Date' to datetime and set as index
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)
df.set_index('Date', inplace=True)

# Set an everyday day by day frequency and fill missing values using forward fill
df = df.asfreq('D')
df['Temp'].fillna(method='ffill', inplace=True)

# Decompose the day by day series (365-day seasonality for yearly patterns)
decomposition = seasonal_decompose(df['Temp'], model='additive', period=365)

# Plot the decomposed components
decomposition.plot()
plt.suptitle('Decomposition of Each day Minimum Temperatures (Each day)', fontsize=14)
plt.tight_layout()
plt.show()

Output:

Decomposition of day by day temperatures showing trend, seasonal cycles and random fluctuations.

The decomposition plot clearly shows a strong seasonal pattern that repeats annually, together with a mild trend that shifts over time. The residual component captures the random noise that isn’t explained by trend or seasonality.

Within the code earlier, you would possibly have noticed that I used an additive model for decomposing the Time Series. But what exactly does that mean — and why is it the proper alternative for this dataset?

Let’s break it down.
In an additive model, we assume Trend, Seasonality and Residuals (Noise) mix linearly, like this:
Y = T ​+ S ​+ R​

Where:
Y is the actual value at time t
T​ is the trend
S is the seasonal component
R is the residual (random noise)

This implies we’re treating the observed value because the sum of the parts, each component contributes independently to the ultimate output.

I selected the additive model because once I checked out the pattern in day by day minimum temperatures, I noticed something essential:

The road plot above shows the day by day minimum temperatures from 1981 to 1990. We will clearly see a powerful seasonal cycle that repeats annually, colder temperatures in winter, warmer in summer.

Importantly, the amplitude of those seasonal swings stays relatively consistent through the years. For instance, the temperature difference between summer and winter doesn’t appear to grow or shrink over time. This stability in seasonal variation is a key sign that the additive model is acceptable for decomposition, because the seasonal component appears to be independent of any trend.

We use an additive model when the trend is comparatively stable and doesn’t amplify or distort the seasonal pattern, and when the seasonality stays inside a consistent range over time, even when there are minor fluctuations.

Now that we understand how the additive model works, let’s explore the multiplicative model — which is commonly used when the seasonal effect scales with the trend which can even help us understand the additive model more clearly.

Consider a household’s electricity consumption. Suppose the household uses 20% more electricity in summer in comparison with winter. Meaning the seasonal effect isn’t a hard and fast number — it’s a proportion of their baseline usage.

Let’s see how this looks with real numbers:

In 2021, the household used 300 kWh in winter and 360 kWh in summer (20% greater than winter).

In 2022, their winter consumption increased to 330 kWh, and summer usage rose to 396 kWh (still 20% greater than winter).

In each years, the seasonal difference grows with the trend   from +60 kWh in 2021 to +66 kWh in 2022   though the percentage increase stays the identical. This is strictly the sort of behavior that a multiplicative model captures well.

In mathematical terms:
Y = T ×S ×R 
Where:
Y​: Observed value
T: Trend component
S: Seasonal component
R​: Residual (noise)

By taking a look at the decomposition plot, we are able to work out whether an additive or multiplicative model suits our data higher.

There are also other powerful decomposition tools available, which I’ll be covering in considered one of my upcoming blog posts.Now that we now have a transparent understanding of additive and multiplicative models, let’s shift our focus to applying a baseline model that matches this dataset.

Based on the decomposition plot, we are able to see a powerful seasonal pattern in the information, which suggests that a Seasonal Naive model is perhaps a superb fit for this time series.

This model assumes that the worth at a given time will probably be the same because it was in the identical period of the previous season — making it a straightforward yet effective alternative when seasonality is dominant and consistent. For instance, if temperatures typically follow the identical yearly cycle, then the forecast for July 1st, 1990, would simply be the temperature recorded on July 1st, 1989.

Code:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# Load the dataset
df = pd.read_csv("minimum day by day temperatures data.csv")

# Convert 'Date' column to datetime and set as index
df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)
df.set_index('Date', inplace=True)

# Ensure regular day by day frequency and fill missing values
df = df.asfreq('D')
df['Temp'].fillna(method='ffill', inplace=True)

# Step 1: Create the Seasonal Naive Forecast
seasonal_period = 365  # Assuming yearly seasonality for day by day data
# Create the Seasonal Naive forecast by shifting the temperature values by 12 months
df['Seasonal_Naive'] = df['Temp'].shift(seasonal_period)

# Step 2: Plot the actual vs forecasted values
# Plot the last 2 years (730 days) of information to check
plt.figure(figsize=(12, 5))
plt.plot(df['Temp'][-730:], label='Actual')
plt.plot(df['Seasonal_Naive'][-730:], label='Seasonal Naive Forecast', linestyle='--')
plt.title('Seasonal Naive Forecast vs Actual Temperatures')
plt.xlabel('Date')
plt.ylabel('Temperature (°C)')
plt.legend()
plt.tight_layout()
plt.show()

# Step 3: Evaluate using MAPE (Mean Absolute Percentage Error)
# Use the last 12 months for testing
test = df[['Temp', 'Seasonal_Naive']].iloc[-365:].copy()
test.dropna(inplace=True)

# MAPE Calculation
mape = np.mean(np.abs((test['Temp'] - test['Seasonal_Naive']) / test['Temp'])) * 100
print(f"MAPE (Seasonal Naive Forecast): {mape:.2f}%")

Output:

Seasonal Naive Forecast vs. Actual Temperatures (1989–1990)

To maintain the visualization clear and focused, we’ve plotted the last two years of the dataset (1989–1990) as an alternative of all 10 years.

This plot compares the actual day by day minimum temperatures in Melbourne with the values predicted by the Seasonal Naive model, which simply assumes that every day’s temperature will probably be the identical because it was on the same day one yr ago.

As seen within the plot, the Seasonal Naive forecast captures the broad shape of the seasonal cycles quite well — it mirrors the rise and fall of temperatures all year long. Nonetheless, it doesn’t capture day-to-day variations, nor does it reply to slight shifts in seasonal timing. This is predicted, because the model is designed to repeat the previous yr’s pattern exactly, without adjusting for trend or noise.

To judge how well this model performs, we calculate the Mean Absolute Percentage Error (MAPE) over the ultimate 12 months of the dataset (i.e., 1990). We only use this era since the Seasonal Naive forecast needs a full yr of historical data before it could begin making predictions.

Mean Absolute Percentage Error (MAPE) is a commonly used metric to judge the accuracy of forecasting models. It measures the average absolute difference between the actual and predicted values, expressed as a percentage of the particular values.

In time series forecasting, we typically evaluate model performance on the most up-to-date or goal time period — not on the center years. This reflects how forecasts are utilized in the actual world: we construct models on historical data to predict what’s coming next.

That’s why we calculate MAPE only on the final 12 months of the dataset — this simulates forecasting for a future and offers us a practical measure of how well the model would perform in practice.

A MAPE of 28.23%, which supplies us a baseline level of forecasting error. Any model we construct next — whether it’s customized or more advanced, should aim to outperform this benchmark.

A MAPE of 28.23% signifies that, on average, the model’s predictions were 28.23% off from the actual day by day temperature values over the past yr.

In other words, if the true temperature on a given day was 10°C, the Seasonal Naïve forecast may need been around 7.2°C or 12.8°C, reflecting a 28% deviation.

I’ll dive deeper into evaluation metrics in a future post.

On this post, we laid the muse for time series forecasting by understanding how real-world data could be broken down into trend, seasonality, and residuals through decomposition. We explored the difference between additive and multiplicative models, implemented the Seasonal Naive baseline forecast and evaluated its performance using MAPE.

While the Seasonal Naive model is straightforward and intuitive, it comes with limitations especially for this dataset. It assumes that the temperature on any given day is similar to the identical day last yr. But because the plot and MAPE of 28.23% showed, this assumption doesn’t hold perfectly. The information displays slight shifts in seasonal patterns and long-term variations that the model fails to capture.

In the following a part of this series, we’ll go further. We’ll explore the right way to customize a baseline model, compare it to the Seasonal Naive approach and evaluate which one performs higher using error metrics like MAPE, MAE and RMSE.

We’ll also begin constructing the muse needed to grasp more advanced models like ARIMA including key concepts comparable to:

  • Stationarity
  • Autocorrelation and Partial Autocorrelation 
  • Differencing
  • Lag-based modeling (AR and MA terms)

Part 2 will dive into these topics in additional detail, starting with custom baselines and ending with the foundations of ARIMA.

Thanks for reading.  I hope you found this post helpful and insightful.

ASK ANA

What are your thoughts on this topic?
Let us know in the comments below.

0 0 votes
Article Rating
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Share this article

Recent posts

0
Would love your thoughts, please comment.x
()
x