The Air Passengers dataset on Kaggle (https://www.kaggle.com/datasets/rakannimer/air-passengers) records monthly international airline passenger totals from January 1949 to December 1960 (in thousands). This classic Box & Jenkins series is a popular teaching example because it clearly displays trend and seasonality in just 144 observations.
What Is Time Series Data?Time series data consists of observations collected at regular time intervals. The order matters—each value depends on previous ones. Examples include stock prices, monthly sales, and the passenger counts in this dataset. The key feature is temporal dependence, which allows us to detect patterns and make forecasts.
Time Series DecompositionDecomposition splits a series into underlying components for easier analysis. A series can be modeled as:
Y_t- Additive:
Y_t = T_t + S_t + R_t - Multiplicative:
Y_t = T_t \times S_t \times R_t
- Trend – Long-term upward or downward movement (clear growth in air travel here).
- Seasonality – Regular repeating patterns (summer peaks and winter drops every year).
- Residual – Remaining random variation after trend and seasonality are removed.
Python Code from Grok
# ============================================================
# Air Passengers Time Series Decomposition
# Dataset: rakannimer/air-passengers (or ashfakyeafi version)
# ============================================================
import os
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose
from kaggle.api.kaggle_api_extended import KaggleApi
# ---------- 1. Authenticate ----------
# Use a NEW Kaggle token (revoke the old one you shared earlier)
os.environ['KAGGLE_USERNAME'] = 'xxxxxxxx'
os.environ['KAGGLE_KEY'] = 'xxxxxxxxxxxxxxxxxxx'
api = KaggleApi()
api.authenticate()
# ---------- 2. Download the dataset ----------
dataset = "rakannimer/air-passengers" # classic version
# Alternative: "ashfakyeafi/air-passenger-data-for-time-series-analysis"
download_path = "./air_passengers"
os.makedirs(download_path, exist_ok=True)
api.dataset_download_files(dataset, path=download_path, unzip=True)
print("Dataset downloaded successfully!\n")
# ---------- 3. Load and prepare the data ----------
# The file is usually named AirPassengers.csv
csv_file = os.path.join(download_path, "AirPassengers.csv")
# Fallback if the name is slightly different
if not os.path.exists(csv_file):
csv_files = [f for f in os.listdir(download_path) if f.endswith('.csv')]
csv_file = os.path.join(download_path, csv_files[0])
print(f"Using file: {csv_files[0]}")
df = pd.read_csv(csv_file)
print("Raw data preview:")
print(df.head())
print("\nColumns:", df.columns.tolist())
# Standardize column names
df.columns = ['Month', 'Passengers'] # rename if needed
# Convert Month to datetime and set as index
df['Month'] = pd.to_datetime(df['Month'])
df.set_index('Month', inplace=True)
df = df.asfreq('MS') # Monthly Start frequency
print("\nPrepared time series:")
print(df.head(12))
print(f"\nTotal observations: {len(df)}")
# ---------- 4. Plot the original series ----------
plt.figure(figsize=(12, 5))
plt.plot(df['Passengers'], label='Air Passengers')
plt.title('Monthly International Airline Passengers (1949–1960)')
plt.xlabel('Year')
plt.ylabel('Number of Passengers (in thousands)')
plt.grid(True, alpha=0.3)
plt.legend()
plt.tight_layout()
plt.show()
# ---------- 5. Time Series Decomposition ----------
# Multiplicative model is better for this dataset
# (seasonal amplitude increases with the trend)
decomposition = seasonal_decompose(
df['Passengers'],
model='multiplicative', # try 'additive' as comparison
period=12 # yearly seasonality
)
# ---------- 6. Plot the components ----------
fig = decomposition.plot()
fig.set_size_inches(12, 9)
fig.suptitle('Air Passengers – Time Series Decomposition\n(Trend + Seasonal + Residual)', fontsize=14, y=1.02)
plt.tight_layout()
plt.show()
# Optional: access the individual components
trend = decomposition.trend
seasonal = decomposition.seasonal
residual = decomposition.resid
print("\nDecomposition completed successfully!")
print("You can now use: trend, seasonal, residual")
No comments:
Post a Comment