Mathew K Analytics

Lesson 16 · Python For Time Series

Understanding Trend, Seasonality, Cyclicity, and Noise in Time Series Analysis

In this lesson, we will learn what time series data is, and explore its key patterns like trend, seasonality, cyclicity, and noise. We will use real-world…

⬇ Download notebookOpen in Colab ↗

What you'll learn

Data

No separate download needed — the notebook creates or downloads everything it uses.

📓 Full notebook

Download .ipynb
 

Welcome to Time Series Fundamentals: Trend, Seasonality, Cyclicity, and Noise#

In this lesson, we will learn what time series data is, and explore its key patterns like trend, seasonality, cyclicity, and noise.

We will use real-world data like climate records and sales figures.

Do not worry if you are brand new to Python follow along, try the examples, and you will get the hang of it quickly!

Let us start our journey together!

# Step 1: Python setup and warning suppression
import warnings
warnings.filterwarnings("ignore")
print("Hello! Welcome to your time series adventure.")
Hello! Welcome to your time series adventure.

What is Time Series Data?#

Time series data simply means measurements taken over time.

Examples: daily temperatures, monthly sales, or the number of website visitors each hour.

Patterns can often be found in this data, and we can use Python to help us spot them!

# Data setup: Let us load daily minimum temperature data
import pandas as pd
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/daily-min-temperatures.csv"
data = pd.read_csv(url)
print("Data shape:", data.shape)
print("First 5 rows:")
print(data.head())
Data shape: (3650, 2)
First 5 rows:
         Date  Temp
0  1981-01-01  20.7
1  1981-01-02  17.9
2  1981-01-03  18.8
3  1981-01-04  14.6
4  1981-01-05  15.8
# Plot the temperature time series
import matplotlib.pyplot as plt
plt.figure(figsize=(10,4))
plt.plot(data["Temp"])
plt.title("Daily Minimum Temperatures")
plt.xlabel("Day")
plt.ylabel("Temperature (C)")
plt.grid(True)
plt.show()
No description has been provided for this image

Spotting Trend in the Data#

A trend is a long-term increase or decrease in the data over time.

It is like noticing that winters are getting warmer every year.

Let us check for trend in our temperature data.

# Calculate and plot a rolling mean (trend line)
data["Trend"] = data["Temp"].rolling(window=365).mean()
plt.figure(figsize=(10,4))
plt.plot(data["Temp"], label="Daily")
plt.plot(data["Trend"], color="red", linewidth=3, label="Trend (365-day avg)")
plt.title("Trend in Daily Temperatures")
plt.legend()
plt.show()
No description has been provided for this image

What is Seasonality?#

Seasonality means patterns that repeat at regular times like warmer summers and colder winters.

This happens again and again, like the changing seasons each year.

Let us hunt for seasonality in our temperature data next.

# Highlighting seasonality with monthly averages
data["Month"] = pd.to_datetime(data["Date"]).dt.month
monthly_means = data.groupby("Month")["Temp"].mean()
plt.figure(figsize=(8,4))
plt.bar(monthly_means.index, monthly_means.values)
plt.title("Average Temperature by Month")
plt.xlabel("Month (1=Jan, 12=Dec)")
plt.ylabel("Average Temp (C)")
plt.show()
No description has been provided for this image

Cyclic Patterns in Time Series#

Cyclic patterns are up-and-down waves that do not happen on a regular schedule.

Unlike seasonality, cycles could last a few years and are not tied to the calendar.

Think of things like economic booms and busts happening at uncertain intervals.

Let us see how to spot cycles.

# Use smoothing to try spotting cycles (longer rolling window)
data["Cyclic"] = data["Temp"].rolling(window=730).mean()  # about 2 years
plt.figure(figsize=(10,4))
plt.plot(data["Temp"], alpha=0.3, label="Daily Temps")
plt.plot(data["Cyclic"], color="purple", linewidth=3, label="Cyclic (2yr avg)")
plt.title("Possible Cyclic Patterns in Temperature")
plt.legend()
plt.show()
No description has been provided for this image

What is Noise?#

Noise is the randomness or unexpected bumps in the data.

It is like static on a radio it makes real patterns harder to see.

We will see how to spot and understand noise.

# Visualizing noise: subtract trend and seasonality
noisy_values = data["Temp"] - data["Trend"]
plt.figure(figsize=(10,4))
plt.plot(noisy_values, color="gray")
plt.title("Just the Noise (original minus trend)")
plt.xlabel("Day")
plt.ylabel("Noise")
plt.show()
No description has been provided for this image
# Error handling: what if a column is missing?
try:
    data["FakeCol"]
except KeyError:
    print("Column not found! Check your spelling or column names.")
    
Column not found! Check your spelling or column names.
# Updating data with new columns: flag cold days
data["ColdDay"] = data["Temp"] < 5
print(data[["Date", "Temp", "ColdDay"]].head())
         Date  Temp  ColdDay
0  1981-01-01  20.7    False
1  1981-01-02  17.9    False
2  1981-01-03  18.8    False
3  1981-01-04  14.6    False
4  1981-01-05  15.8    False
# Remove unwanted columns safely
if "FakeCol" in data.columns:
    data = data.drop(columns=["FakeCol"])
print("Columns now:", data.columns.tolist())
Columns now: ['Date', 'Temp', 'Trend', 'Month', 'Cyclic', 'ColdDay']
# Useful: Count number of cold days
num_cold = data["ColdDay"].sum()
print(f"Number of cold days: {num_cold}")
Number of cold days: 198
# Loop: print the first 5 cold days
count = 0
for idx, row in data.iterrows():
    if row["ColdDay"]:
        print(row["Date"], row["Temp"])
        count += 1
        if count == 5:
            break
        
1981-05-19 3.2
1981-05-20 2.1
1981-05-21 3.4
1981-06-07 2.5
1981-06-08 3.5
# List comprehensions: list years with more than 60 cold days
data["Year"] = pd.to_datetime(data["Date"]).dt.year
years = data["Year"].unique()
cold_years = [year for year in years if data[data["Year"] == year]["ColdDay"].sum() > 60]
print(cold_years)
[]
# Sorting: hottest days in the dataset
hottest = data.sort_values("Temp", ascending=False).head(5)
print(hottest[["Date","Temp"]])
           Date  Temp
410  1982-02-15  26.3
384  1982-01-20  25.2
14   1981-01-15  25.0
39   1981-02-09  25.0
17   1981-01-18  24.8
# Filtering: only show summer months (Dec-Jan-Feb in Australia)
summer = data[data["Month"].isin([12,1,2])]
print(summer[["Date","Temp"]].head())
         Date  Temp
0  1981-01-01  20.7
1  1981-01-02  17.9
2  1981-01-03  18.8
3  1981-01-04  14.6
4  1981-01-05  15.8
# Combining data: average summer vs. winter temperature
winter = data[data["Month"].isin([6,7,8])]
avg_summer = summer["Temp"].mean()
avg_winter = winter["Temp"].mean()
print(f"Avg summer temp: {avg_summer:.1f} C, Avg winter temp: {avg_winter:.1f} C")
Avg summer temp: 14.7 C, Avg winter temp: 7.3 C
# Mini-project: ask user for a temperature cutoff and count
cut = input("Enter a temperature cutoff (Celsius): ")
cut = float(cut)
below = data[data["Temp"] < cut]
print(f"Number of days below {cut}C: {len(below)}")
Number of days below 10.0C: 1442
 
# Mini-project, part 2: plot those cold days you chose
plt.figure(figsize=(10,4))
plt.plot(data["Temp"], label="All temps")
plt.scatter(below.index, below["Temp"], color="red", label="Below cutoff")
plt.axhline(y=cut, color="red", linestyle="--")
plt.title(f"Days Below {cut} Celsius")
plt.legend()
plt.show()
No description has been provided for this image

Best Practices for Time Series Analysis#

Always plot before you analyze pictures reveal hidden details.

Check for missing data and odd values.

Try different window sizes for rolling averages to spot both short and long patterns.

Document your steps with comments so others can learn from you!

# Troubleshooting: handle missing values
missing = data["Temp"].isnull().sum()
print("Missing temperature values:", missing)
if missing > 0:
    data["Temp"] = data["Temp"].fillna(data["Temp"].mean())
    print("Filled missing values with the mean.")
    
Missing temperature values: 0
# Quick tip: see which columns are numeric
numeric_cols = data.select_dtypes(include="number").columns.tolist()
print(numeric_cols)
['Temp', 'Trend', 'Month', 'Cyclic', 'Year']
# Challenge: ask for a month number, count days above 20C
m = input("Pick a month number (1-12): ")
m = int(m)
in_month = data[data["Month"] == m]
above_20 = in_month[in_month["Temp"] > 20]
print(f"Days above 20C in month {m}: {len(above_20)}")
Days above 20C in month 1: 20
 

Quick Review#

In this lesson, you learned:

  • What time series data is
  • How to spot trend, seasonality, cycles, and noise
  • How to work with real datasets using Python
  • How to visualize and analyze patterns in data

You are now ready to explore your own time series!

Thank You! What Next?#

Thank you for joining this beginner time series lesson.

Subscribe to the channel for more Python and data science tutorials.

Try these ideas on your own data and share your results!

Happy coding!

Found this useful?

All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.