Mathew K Analytics

Lesson 4 · Python for Retail E-commerce Analytics

Retail Analytics Workflow Using Python: Step-by-Step Training for E-commerce Data

In this lesson, we tackle a typical retail analytics business problem: how do we understand our sales patterns and customer behavior using Python? Analytics…

⬇ 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

Retail Analytics Workflow Using Python#

  • In this lesson, we tackle a typical retail analytics business problem: how do we understand our sales patterns and customer behavior using Python?
  • Analytics helps make better inventory, sales, and marketing decisions by providing insights into what products sell, who buys them, and when.
  • You will learn to load real retail datasets, calculate sales metrics, identify top products, segment customers, and prevent common errors in retail data analysis.
  • By the end, you will produce actionable insights that can drive improvements in product assortment, customer targeting, and revenue growth.
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')

Core Retail Analytics Concepts#

  • Retail datasets can include transactions, customer orders, product catalogs, or market basket information.
  • Key sales metrics: revenue (total money earned), quantity sold, and price per unit.
  • Beginner mistakes include: misinterpreting price versus revenue, forgetting to group by product or customer, and not handling missing data.
# Beginner Example 1: Load retail transactions dataset
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00502/online_retail_II.xlsx'
df = pd.read_excel(url, sheet_name='Year 2010-2011')
df['InvoiceDate'] = pd.to_datetime(df['InvoiceDate'])
print(df.shape)
print(df.head(3))
(541910, 8)
  Invoice StockCode                         Description  Quantity  \
0  536365    85123A  WHITE HANGING HEART T-LIGHT HOLDER         6   
1  536365     71053                 WHITE METAL LANTERN         6   
2  536365    84406B      CREAM CUPID HEARTS COAT HANGER         8   

          InvoiceDate  Price  Customer ID         Country  
0 2010-12-01 08:26:00   2.55      17850.0  United Kingdom  
1 2010-12-01 08:26:00   3.39      17850.0  United Kingdom  
2 2010-12-01 08:26:00   2.75      17850.0  United Kingdom  
# Beginner Example 2: Preview unique products sold
unique_products = df['Description'].nunique()
print('Unique products sold:', unique_products)
Unique products sold: 4223
# Beginner Example 3: Calculate basic revenue column
df['Revenue'] = df['Quantity'] * df['Price']
print(df[['Quantity', 'Price', 'Revenue']].head(5))
   Quantity  Price  Revenue
0         6   2.55    15.30
1         6   3.39    20.34
2         8   2.75    22.00
3         6   3.39    20.34
4         6   3.39    20.34
# Intermediate Example 1: Total revenue per country
revenue_by_country = df.groupby('Country')['Revenue'].sum().sort_values(ascending=False)
print(revenue_by_country.head(5))
Country
United Kingdom    8187806.364
Netherlands        284661.540
EIRE               263276.820
Germany            221698.210
France             197421.900
Name: Revenue, dtype: float64
# Intermediate Example 2: Average order size
avg_order_size = df.groupby('Invoice')['Quantity'].sum().mean()
print('Average number of items per order:', round(avg_order_size, 2))
Average number of items per order: 199.86
# Intermediate Example 3: Find top customers by spending
top_customers = df.groupby('Customer ID')['Revenue'].sum().sort_values(ascending=False).head(5)
print(top_customers)
Customer ID
14646.0    279489.02
18102.0    256438.49
17450.0    187482.17
14911.0    132572.62
12415.0    123725.45
Name: Revenue, dtype: float64
# Intermediate Example 4: Sales trend over time (monthly)
df['InvoiceMonth'] = df['InvoiceDate'].dt.to_period('M')
monthly_revenue = df.groupby('InvoiceMonth')['Revenue'].sum()
print(monthly_revenue.head(12))
InvoiceMonth
2010-12     748957.020
2011-01     560000.260
2011-02     498062.650
2011-03     683267.080
2011-04     493207.121
2011-05     723333.510
2011-06     691123.120
2011-07     681300.111
2011-08     682680.510
2011-09    1019687.622
2011-10    1070704.670
2011-11    1461756.250
Freq: M, Name: Revenue, dtype: float64
# Intermediate Example 5: Most popular products (by volume)
product_sales = df.groupby('Description')['Quantity'].sum().sort_values(ascending=False).head(5)
print(product_sales)
Description
WORLD WAR 2 GLIDERS ASSTD DESIGNS    53847
JUMBO BAG RED RETROSPOT              47363
ASSORTED COLOUR BIRD ORNAMENT        36381
POPCORN HOLDER                       36334
PACK OF 72 RETROSPOT CAKE CASES      36039
Name: Quantity, dtype: int64
# Advanced Example 1: Combine transactions with customer order dataset
np.random.seed(42)
n_orders = 1000
order_ids = list(range(1,n_orders+1))
customer_ids = np.random.randint(1000,1500,n_orders)
product_ids = np.random.randint(1001,1100,n_orders)
quantities = np.random.randint(1,5,n_orders)
order_dates = pd.date_range('2023-01-01', periods=n_orders, freq='h')
orders = pd.DataFrame({'OrderID':order_ids,'CustomerID':customer_ids,'ProductID':product_ids,'Quantity':quantities,'OrderDate':order_dates})
print('Orders loaded:', orders.shape)
Orders loaded: (1000, 5)
# Advanced Example 2: Create a product catalog and join with orders
np.random.seed(42)
categories = ['Electronics','Clothing','Home','Sports','Beauty']
product_ids = list(range(1001,1101))
product_categories = np.random.choice(categories,100)
product_prices = np.round(np.random.uniform(5,500,100),2)
catalog = pd.DataFrame({'ProductID':product_ids,'Category':product_categories,'Price':product_prices})
orders_catalog = pd.merge(orders, catalog, on='ProductID', how='left')
print(orders_catalog.head(3))
   OrderID  CustomerID  ProductID  Quantity           OrderDate     Category  \
0        1        1102       1049         3 2023-01-01 00:00:00     Clothing   
1        2        1435       1011         1 2023-01-01 01:00:00       Sports   
2        3        1348       1085         3 2023-01-01 02:00:00  Electronics   

    Price  
0  155.87  
1  194.55  
2  409.13  
# Advanced Example 3: Calculate average order value per customer
orders_catalog['OrderValue'] = orders_catalog['Quantity'] * orders_catalog['Price']
avg_value_per_customer = orders_catalog.groupby('CustomerID')['OrderValue'].mean().sort_values(ascending=False)
print(avg_value_per_customer.head(5))
CustomerID
1242    1967.16
1490    1882.24
1049    1882.24
1215    1831.64
1375    1815.52
Name: OrderValue, dtype: float64
# Advanced Example 4: Category revenue contribution
category_revenue = orders_catalog.groupby('Category')['OrderValue'].sum().sort_values(ascending=False)
print(category_revenue)
Category
Sports         147783.07
Beauty         134105.61
Clothing       121487.00
Home            98098.72
Electronics     92256.84
Name: OrderValue, dtype: float64
# Advanced Example 5: Market Basket - most common co-occurring products
products = ['Bread','Milk','Butter','Eggs','Apples','Chicken','Rice','Cheese']
transaction_ids = np.repeat(np.arange(1,301),3)
product_choices = np.random.choice(products,len(transaction_ids))
basket_df = pd.DataFrame({'TransactionID':transaction_ids,'Product':product_choices})
freq = basket_df.groupby(['TransactionID', 'Product']).size().reset_index(name='Count')
cooccurrence = freq.pivot_table(index='TransactionID', columns='Product', values='Count', fill_value=0)
from itertools import combinations
from collections import Counter
pairs = []
for row in cooccurrence.iterrows():
    items = row[1][row[1] > 0].index.tolist()
    pairs.extend(combinations(sorted(items), 2))
pair_counts = Counter(pairs)
print(pair_counts.most_common(5))
[(('Bread', 'Eggs'), 28), (('Bread', 'Rice'), 28), (('Apples', 'Bread'), 28), (('Cheese', 'Chicken'), 27), (('Cheese', 'Eggs'), 27)]
# Error Handling Example 1: Check for missing prices
missing_price = df['Price'].isnull().sum()
print('Missing price entries:', missing_price)
Missing price entries: 0
# Error Handling Example 2: Remove transactions with missing Customer ID
original_rows = df.shape[0]
df_clean = df.dropna(subset=['Customer ID'])
print('Removed', original_rows - df_clean.shape[0], 'transactions with missing Customer ID')
Removed 135080 transactions with missing Customer ID
# Error Handling Example 3: Catching grouping errors
try:
    wrong_agg = df.groupby('Description')['Revenue'].mean()[0]
except Exception as e:
    print('Example grouping error:', str(e))
Example grouping error: 0

Best Practices and Common Retail Analytics Patterns#

  • Segment customers by spend or frequency to improve targeting.
  • Use category performance reports to inform purchasing decisions.
  • Apply market basket analysis to create product bundles or recommend related items.
  • Forecast demand and seasons using monthly sales trends.
  • Always validate data sources, check column types, and handle missing or outlier values.
# End-to-End Example: Identify top-selling products and provide a recommendation
top_products = df.groupby('Description')['Quantity'].sum().sort_values(ascending=False).head(3)
print('Top selling products by volume:')
print(top_products)
recommendation = f"Consider increasing inventory and marketing for '{top_products.index[0]}' to capture more sales, since it leads in units sold."
print('Business recommendation:', recommendation)
Top selling products by volume:
Description
WORLD WAR 2 GLIDERS ASSTD DESIGNS    53847
JUMBO BAG RED RETROSPOT              47363
ASSORTED COLOUR BIRD ORNAMENT        36381
Name: Quantity, dtype: int64
Business recommendation: Consider increasing inventory and marketing for 'WORLD WAR 2 GLIDERS ASSTD DESIGNS' to capture more sales, since it leads in units sold.

Next Steps: Continue Practicing Retail Analytics#

  • Continue strengthening your analytics skills with more real retail datasets.
  • Try visualizations, run market basket analysis, and forecast future trends.
  • For more detailed video tutorials, search for "retail analytics Python" on YouTube!

Found this useful?

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