EthicsComputerCourses
Join training +91 90532 10052

Time Series Introduction

Time Series · Lesson 2 of 31 Intermediate 6 min read Updated

By the end of this lesson you will be able to say what a time series is, spot the patterns inside one, and make three simple forecasts for next month. You will also see why the simplest forecast is sometimes the best one.

What is a time series?

A time series is a list of measurements taken in time order, usually at a regular gap. The gap is called the frequency: every hour, every day, every month.

You meet time series everywhere in India:

  • The number of passengers at Jaipur railway station each day.
  • Monthly electricity units on your home bill.
  • Daily rainfall in Kochi during the monsoon.
  • A kirana shop's sales each month.

Forecasting means using the past values of a series to estimate its future values. A shopkeeper who orders extra sweets before Diwali is forecasting, even without any code.

The order of the rows is the most important fact about a time series. If you shuffle a class register, nothing is lost. If you shuffle a year of sales, the story disappears, because each month is linked to the months around it.

The example series for this course

Most lessons use the same series: monthly sales of a kirana (grocery) shop in Jaipur, in thousands of rupees, from January 2019 to December 2025. The data is invented with NumPy, so we know exactly which patterns are inside it. That lets you check whether a method finds them.

Step 1. Run the code and read the first five months.

PythonRun it yourself
import numpy as np
import pandas as pd

def make_sales(seed=1):
    """Monthly sales (thousand rupees) of a Jaipur kirana shop, Jan 2019 to Dec 2025."""
    rng = np.random.default_rng(seed)
    months = pd.date_range("2019-01-01", "2025-12-01", freq="MS")
    t = np.arange(len(months))
    season = np.array([0.95, 0.92, 1.0, 0.98, 0.97, 0.93, 0.86, 0.88, 0.96, 1.22, 1.28, 1.05])
    sales = (180 + 1.5 * t) * season[months.month - 1] + rng.normal(0, 6, len(t))
    return pd.Series(sales.round(1), index=months, name="sales")

sales = make_sales()
print(sales.head())
print("Months of data:", len(sales))
print("First month:", sales.index[0].date(), " Last month:", sales.index[-1].date())
Output
2019-01-01    173.1
2019-02-01    171.9
2019-03-01    185.0
2019-04-01    173.0
2019-05-01    185.9
Freq: MS, Name: sales, dtype: float64
Months of data: 84
First month: 2019-01-01  Last month: 2025-12-01

You should see 84 months. Each label is the first day of a month, which pandas calls MS (month start). The make_sales function has three parts, and they are the three parts of almost every real series:

  1. Trend: 180 + 1.5 * t grows by Rs 1,500 a month as the colony grows.
  2. Seasonality: the season list repeats every year. July is weak (monsoon, fewer visitors) and October and November are strong (Diwali shopping).
  3. Noise: rng.normal(0, 6, ...) adds random ups and downs nobody can predict.

Look before you forecast

Step 2. Draw the series and print the average for each calendar month.

PythonRun it yourself
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def make_sales(seed=1):
    """Monthly sales (thousand rupees) of a Jaipur kirana shop, Jan 2019 to Dec 2025."""
    rng = np.random.default_rng(seed)
    months = pd.date_range("2019-01-01", "2025-12-01", freq="MS")
    t = np.arange(len(months))
    season = np.array([0.95, 0.92, 1.0, 0.98, 0.97, 0.93, 0.86, 0.88, 0.96, 1.22, 1.28, 1.05])
    sales = (180 + 1.5 * t) * season[months.month - 1] + rng.normal(0, 6, len(t))
    return pd.Series(sales.round(1), index=months, name="sales")

sales = make_sales()
fig, ax = plt.subplots(figsize=(9, 3.5))
ax.plot(sales.index, sales.values, color="#4f46e5")
ax.set_title("Monthly sales of a Jaipur kirana shop")
ax.set_ylabel("Sales (thousand Rs)")
plt.show()

by_month = sales.groupby(sales.index.month).mean().round(1)
print("Average by calendar month:")
print(by_month.to_string())
Output
Average by calendar month:
1     219.1
2     215.9
3     236.5
4     232.0
5     233.2
6     222.2
7     210.5
8     213.0
9     236.1
10    304.2
11    319.0
12    262.9

The chart climbs from left to right, with a sharp peak every October and November. The table confirms it: November averages about 319, July only about 210. Notice how quickly the chart shows the pattern. Always plot a series before you model it, just as a doctor looks at you before writing a prescription.

Your first three forecasts

Pretend today is 30 September 2025. You know every month up to September and must guess October. Here are three simple ideas a shopkeeper might use.

Step 3. Run the code and compare each guess with what really happened.

PythonRun it yourself
import numpy as np
import pandas as pd

def make_sales(seed=1):
    """Monthly sales (thousand rupees) of a Jaipur kirana shop, Jan 2019 to Dec 2025."""
    rng = np.random.default_rng(seed)
    months = pd.date_range("2019-01-01", "2025-12-01", freq="MS")
    t = np.arange(len(months))
    season = np.array([0.95, 0.92, 1.0, 0.98, 0.97, 0.93, 0.86, 0.88, 0.96, 1.22, 1.28, 1.05])
    sales = (180 + 1.5 * t) * season[months.month - 1] + rng.normal(0, 6, len(t))
    return pd.Series(sales.round(1), index=months, name="sales")

sales = make_sales()
history = sales[:"2025-09-01"]          # pretend today is the end of September 2025
actual = sales["2025-10-01"]

guesses = {
    "Same as last month": history.iloc[-1],
    "Average of last 3 months": history.iloc[-3:].mean(),
    "Same month last year": history["2024-10-01"],
}
print("Actual October 2025:", actual)
for name, guess in guesses.items():
    print(f"{name:<26} {guess:6.1f}   error {actual - guess:+6.1f}")
Output
Actual October 2025: 369.0
Same as last month          292.7   error  +76.3
Average of last 3 months    269.2   error  +99.8
Same month last year        347.4   error  +21.6

"Same month last year" wins easily, missing by about 22 thousand rupees. The other two ignore the Diwali season, so they guess far too low. The averaging method is even worse than "last month", because it mixes in the weak monsoon months.

This small test teaches the whole course in miniature. A good forecast must respect the patterns in the data. It must also be tested on months it has not seen. And every clever model must beat these simple ideas, called baselines, before anyone trusts it.

What this course covers

PartYou will learn
Dates and resamplingStore dates in pandas, change daily data to weekly or monthly, smooth with rolling windows
PatternsSplit a series into trend, seasonality and noise; test stationarity; read autocorrelation
MeasuringMAE, RMSE and MAPE; splitting by time; walk-forward validation
Classical modelsBaselines, exponential smoothing written by hand, Holt-Winters, ARIMA and SARIMA
Machine learningLag features with scikit-learn, multi-step forecasts, festivals, uncertainty
ProjectA complete monthly demand forecast for a shop

Common mistakes

  • Shuffling the rows. Random train/test splits leak the future into the past.
  • Skipping the plot. A one-minute chart often shows a trend or a broken month that statistics hide.
  • Forgetting seasonality. "Last month" looks sensible until a festival or the monsoon arrives.
  • Trusting a model without a baseline. If "same month last year" is just as good, the model adds nothing.

Key points

  • A time series is a set of values in time order at a regular frequency.
  • Most series contain a trend, seasonality and noise.
  • Plot the series first; the eye spots patterns quickly.
  • Simple baseline forecasts are easy to compute and often hard to beat.
  • Always judge a forecast on data it has not seen.

Exercise

Pretend today is 31 October 2025 and forecast November 2025 with the same three methods. Print each guess and its error. Which method wins this time, and why?

Show solution
Python
import numpy as np
import pandas as pd

def make_sales(seed=1):
    rng = np.random.default_rng(seed)
    months = pd.date_range("2019-01-01", "2025-12-01", freq="MS")
    t = np.arange(len(months))
    season = np.array([0.95, 0.92, 1.0, 0.98, 0.97, 0.93, 0.86, 0.88, 0.96, 1.22, 1.28, 1.05])
    sales = (180 + 1.5 * t) * season[months.month - 1] + rng.normal(0, 6, len(t))
    return pd.Series(sales.round(1), index=months, name="sales")

sales = make_sales()
history = sales[:"2025-10-01"]
actual = sales["2025-11-01"]
guesses = {
    "Same as last month": history.iloc[-1],
    "Average of last 3 months": history.iloc[-3:].mean(),
    "Same month last year": history["2024-11-01"],
}
print("Actual November 2025:", actual)
for name, guess in guesses.items():
    print(f"{name:<26} {guess:6.1f}   error {actual - guess:+6.1f}")
Output
Actual November 2025: 378.1
Same as last month          369.0   error   +9.1
Average of last 3 months    307.2   error  +70.9
Same month last year        372.1   error   +6.0

"Same month last year" wins again, missing by only 6. But "same as last month" is now a close second (9.1), because October and November are both festive months, so October is a good guide to November. The ranking of simple methods changes from month to month, which is why we test them over many months, not one.

Quick Quiz

1. Which of these is a time series?

2. What are the three common parts of a time series?

3. Why did "same month last year" beat "average of last 3 months" for October 2025?

4. What is a baseline forecast?

Learn Time Series with a mentor

Free lessons get you started. Our Data Science & Machine Learning training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call