Lesson 6 · Supply Chain Operations Analytics
Loading and Exploring Supply Chain Datasets
In this lesson, we will learn how to load, clean, and explore real-world supply chain datasets. Loading and understanding your operational data is critical…
- CourseSupply Chain Operations Analytics
- Lesson6 of 27
- Video22 min
- FormatJupyter notebook · 20 code cells
What you'll learn
Data
No separate download needed — the notebook creates or downloads everything it uses.
📓 Full notebook
Download .ipynbLoading and Exploring Supply Chain Datasets#
- In this lesson, we will learn how to load, clean, and explore real-world supply chain datasets.
- Loading and understanding your operational data is critical for supply chain and operations analytics.
- You will learn how to access data from real retail, manufacturing, and logistics sources.
- We will discover common pitfalls and best practices for handling supply chain data.
- By the end, you will be ready to start analyzing and drawing insights from raw data.
import pandas as pd
import openml
import warnings
warnings.filterwarnings('ignore')
Understanding supply chain, inventory, and operations data#
- In supply chain analytics, we typically work with datasets such as transactions, orders, inventory levels, and delivery records.
- The data is often tabular, with each row representing an operational event (for example, an order or shipment).
- Key columns usually include IDs, dates, product codes, quantities, and partner information.
- Common mistakes are missing date conversions, misunderstanding categorical codes, and misaligned joins between tables.
# Example 1: Loading a retail demand dataset (UCI Online Retail II)
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00502/online_retail_II.xlsx'
df_retail = pd.read_excel(url, sheet_name='Year 2010-2011')
df_retail['InvoiceDate'] = pd.to_datetime(df_retail['InvoiceDate'])
print(df_retail.shape)
print(df_retail.head(3))
# Example 2: Loading an order fulfillment dataset (Olist e-commerce orders)
olist_url = 'https://raw.githubusercontent.com/olist/work-at-olist-data/master/datasets/olist_orders_dataset.csv'
df_orders = pd.read_csv(olist_url)
df_orders['order_purchase_timestamp'] = pd.to_datetime(df_orders['order_purchase_timestamp'])
df_orders['order_delivered_customer_date'] = pd.to_datetime(df_orders['order_delivered_customer_date'])
print(df_orders.shape)
print(df_orders.head(3))
# Example 3: Loading a supplier performance dataset (OpenML Supply Chain)
dataset = openml.datasets.get_dataset(42125)
df_supplier, _, _, _ = dataset.get_data(dataset_format='dataframe')
print(df_supplier.shape)
print(df_supplier.head(3))
# Example 4: Loading inventory and operational records (OpenML Inventory Operations)
dataset = openml.datasets.get_dataset(43900)
X, y, _, _ = dataset.get_data(dataset_format='dataframe')
df_inventory_ops = X.copy() if y is None else pd.concat([X, y], axis=1)
print(df_inventory_ops.shape)
print(df_inventory_ops.head(3))
Previewing and summarizing datasets#
- Exploring head() and tail() gives you a quick look at data.
- Use shape and info() to understand dimensions and types.
- Be wary of nulls and inconsistent data types in operational systems.
print('Retail columns:', df_retail.columns.tolist())
print('Order columns:', df_orders.columns.tolist())
print('Supplier columns:', df_supplier.columns.tolist())
print('Retail Info:')
df_retail.info()
print('\nOrder Info:')
df_orders.info()
print('Retail null values:')
print(df_retail.isnull().sum().sort_values(ascending=False).head(7))
print('How many unique customers?')
print(df_retail['Customer ID'].nunique())
print('How many unique StockCodes?')
print(df_retail['StockCode'].nunique())
# Basic aggregation: total sales per country
df_retail['TotalValue'] = df_retail['Quantity'] * df_retail['Price']
country_sales = df_retail.groupby('Country')['TotalValue'].sum().sort_values(ascending=False)
print(country_sales.head(6))
# Group by time: monthly sales trends
df_retail['Month'] = df_retail['InvoiceDate'].dt.to_period('M')
monthly_demand = df_retail.groupby('Month')['TotalValue'].sum()
print(monthly_demand.tail(6))
# Filtering logistics records: delivered orders only
delivered = df_orders[df_orders['order_delivered_customer_date'].notna()]
print('Delivered orders:', delivered.shape[0])
# Example: Finding orders with missing purchase dates
missing_purchase = df_orders[df_orders['order_purchase_timestamp'].isna()]
print('Orders with missing purchase date:', missing_purchase.shape[0])
# Example: Accidentally joining on the wrong column
try:
merged_wrong = pd.merge(df_orders, df_supplier, left_on='order_id', right_on='Supplier ID')
print('Join rows:', merged_wrong.shape[0])
except Exception as e:
print('Error from bad merge:', e)
# Example: Misinterpreting lead time columns
if 'lead_time' in df_supplier.columns:
print(df_supplier['lead_time'].describe())
else:
print('The supplier data does not have a lead_time column.')
Operational analytics best practices#
- Always validate types and ranges for dates, quantities, and currency columns.
- Use groupby and aggregation for all KPI calculations.
- Plot time trends to spot seasonality and outliers.
- Sample your data to spot irregularities early.
# Calculate average delivery lead time (orders)
delivered = df_orders[df_orders['order_delivered_customer_date'].notna()].copy()
delivered['lead_time_days'] = (delivered['order_delivered_customer_date'] - delivered['order_purchase_timestamp']).dt.days
print('Average lead time:', delivered['lead_time_days'].mean())
# Group by product: sales by SKU
sku_sales = df_retail.groupby('StockCode')['TotalValue'].sum().sort_values(ascending=False)
print(sku_sales.head(5))
# Example: Advancedmonthly sales pivot table by country
pivot = df_retail.pivot_table(index='Month', columns='Country', values='TotalValue', aggfunc='sum')
print(pivot.tail(3))
# Example: Correlation analysis for operational drivers
numeric_cols = df_retail.select_dtypes(include='number')
cor_matrix = numeric_cols.corr()
print(cor_matrix[['TotalValue']])
Mini-project: Analyzing delayed deliveries#
- Our goal is to identify the month with the highest number of late deliveries in the Olist order data.
- We will use our datetime columns and groupby skills.
- Real companies use such dashboards to detect bottlenecks and risk.
# Find late deliveries (delivered after estimated date)
df_orders['order_estimated_delivery_date'] = pd.to_datetime(df_orders['order_estimated_delivery_date'])
late = df_orders[(
(df_orders['order_delivered_customer_date'].notna()) &
(df_orders['order_delivered_customer_date'] > df_orders['order_estimated_delivery_date'])
)]
late['late_month'] = late['order_delivered_customer_date'].dt.to_period('M')
late_month_counts = late.groupby('late_month').size().sort_values(ascending=False)
print('Month with most late deliveries:')
print(late_month_counts.head(1))
Great work! Reflections & More Practice#
- You have learned to load, clean, and analyze real supply chain datasets from retail, logistics, and manufacturing sources.
- Practice: What would you look to automate after these first analyses?
- To see more supply chain analytics with real data, search for 'supply chain analytics in python' on YouTube.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



