Mathew K Analytics

Lesson 2 · Python for Retail E-commerce Analytics

Understanding Retail Business Models for E-commerce and Analytics

In this lesson, we explore the structure and data behind retail and e-commerce businesses. We discuss why understanding retail business models helps drive…

⬇ Download notebookOpen in Colab ↗

📓 Full notebook

Download .ipynb

Understanding Retail Business Models#

  • In this lesson, we explore the structure and data behind retail and e-commerce businesses.
  • We discuss why understanding retail business models helps drive better sales, marketing, and inventory decisions.
  • You will use real-world datasets to analyze sales, customers, and products.
  • You will learn to extract actionable business insights from retail data.
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')

Core Concepts in Retail Analytics#

  • Retail datasets often represent transactions, customer orders, product catalogs, and sales records.
  • Sales metrics like revenue, quantity, and price must be interpreted in business context.
  • Beginner mistakes include confusing revenue with quantity, or grouping data incorrectly.
# Load the online retail transactions dataset
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))
(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  

Exploring a Retail Product Catalog#

  • Retailers often use product catalogs to classify inventory by category and price.
  • Product information helps segment sales by category and spot high-value items.
# Simulate a retail product catalog
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)
df_catalog = pd.DataFrame({'ProductID':product_ids,'Category':product_categories,'Price':product_prices})
print(df_catalog.shape)
print(df_catalog.head(3))
(100, 3)
   ProductID Category   Price
0       1001   Sports  457.91
1       1002   Beauty  425.77
2       1003     Home  227.48

Example 1: Basic Sales Aggregation#

  • Let us sum up the quantity of items sold across all transactions.
  • Aggregating quantities reveals overall sales volume.
total_quantity = df_retail['Quantity'].sum()
print('Total items sold:', total_quantity)
Total items sold: 5176451

Example 2: Revenue Calculation#

  • Calculating sales revenue is essential for measuring business health.
  • Revenue = Quantity Price.
df_retail['Revenue'] = df_retail['Quantity'] * df_retail['Price']
total_revenue = df_retail['Revenue'].sum()
print('Total revenue generated:', round(total_revenue, 2))
Total revenue generated: 9747765.93

Example 3: Top-Selling Products#

  • Identifying best sellers informs inventory planning and marketing.
  • Let us rank products by total quantity sold.
top_products = df_retail.groupby('Description')['Quantity'].sum().sort_values(ascending=False).head(5)
print('Top 5 selling products by quantity:')
print(top_products)
Top 5 selling products by quantity:
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

Example 4: Customer Purchase Frequency#

  • Frequent customers are often the most valuable for a retail business.
  • Let us count how many purchases each customer made.
customer_purchase_counts = df_retail['Customer ID'].value_counts().head(5)
print('Top 5 customers by number of purchases:')
print(customer_purchase_counts)
Top 5 customers by number of purchases:
Customer ID
17841.0    7983
14911.0    5903
14096.0    5128
12748.0    4642
14606.0    2782
Name: count, dtype: int64

Example 5: Product Category Performance#

  • Analyzing categories helps retailers know what drives business growth.
  • Let us link transactions to product categories to compare sales among them.
# Simulate joining transactions and catalog by ProductID
np.random.seed(42)
product_map = dict(zip(df_catalog['ProductID'], df_catalog['Category']))
retail_sample = df_retail.copy()
retail_sample['ProductID'] = np.random.choice(df_catalog['ProductID'], len(retail_sample))
retail_sample['Category'] = retail_sample['ProductID'].map(product_map)
category_sales = retail_sample.groupby('Category')['Revenue'].sum().sort_values(ascending=False)
print('Revenue by product category:')
print(category_sales)
Revenue by product category:
Category
Sports         2425686.753
Clothing       2284072.041
Beauty         1863810.950
Electronics    1686586.110
Home           1487610.080
Name: Revenue, dtype: float64

Example 6: Average Order Value#

  • Measuring average order value shows how much customers spend, guiding pricing and upselling.
  • Let us calculate this key business metric.
order_values = df_retail.groupby('Invoice')['Revenue'].sum()
aov = order_values.mean()
print('Average order value:', round(aov, 2))
Average order value: 376.36

Example 7: Time-Based Revenue Trends#

  • Businesses monitor sales over time to detect seasonality and growth.
  • Let us examine monthly revenue from transactions.
df_retail['Month'] = df_retail['InvoiceDate'].dt.to_period('M')
monthly_revenue = df_retail.groupby('Month')['Revenue'].sum()
print('Monthly revenue:')
print(monthly_revenue.head())
Monthly revenue:
Month
2010-12    748957.020
2011-01    560000.260
2011-02    498062.650
2011-03    683267.080
2011-04    493207.121
Freq: M, Name: Revenue, dtype: float64

Example 8: Customer Segmentation by Revenue#

  • High-value customers can be targeted for loyalty programs.
  • Segmenting by customer-level revenue helps marketing efforts.
customer_revenue = df_retail.groupby('Customer ID')['Revenue'].sum().sort_values(ascending=False)
top_customers = customer_revenue.head(5)
print('Top 5 customers by total revenue:')
print(top_customers)
Top 5 customers by total revenue:
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

Example 9: Market Basket Analysis - Product Co-occurrence#

  • Basket analysis discovers which products are bought together.
  • Retailers use these patterns to make cross-selling recommendations.
# Simulate a market basket transactions dataset
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})
basket_counts = basket_df.groupby(['TransactionID','Product']).size().unstack(fill_value=0)
co_occurrence = (basket_counts.T @ basket_counts)
np.fill_diagonal(co_occurrence.values, 0)
print('Product co-occurrence matrix (first 5 products):')
print(co_occurrence.iloc[:5,:5])
Product co-occurrence matrix (first 5 products):
Product  Apples  Bread  Butter  Cheese  Chicken
Product                                        
Apples        0     32      22      33       22
Bread        32      0      34      39       25
Butter       22     34       0      25       21
Cheese       33     39      25       0       27
Chicken      22     25      21      27        0

Error Handling Example: Missing Transaction Data#

  • Retail datasets often have missing values in key fields like quantity or customer ID.
  • Missing values can bias sales calculations or segmentation.
missing_qty = df_retail['Quantity'].isnull().sum()
missing_cust = df_retail['Customer ID'].isnull().sum()
print('Missing quantities:', missing_qty)
print('Missing customer IDs:', missing_cust)
# Clean sample: remove missing customer ID rows
df_clean = df_retail.dropna(subset=['Customer ID'])
print('After cleaning, rows:', df_clean.shape[0])
Missing quantities: 0
Missing customer IDs: 135080
After cleaning, rows: 406830

Error Handling Example: Incorrect Aggregations#

  • Summing up prices without weighting by quantity leads to wrong revenue figures.
  • Carefully compute revenue as price times quantity.
# Incorrect aggregation: sum of prices only
incorrect_total = df_retail['Price'].sum()
# Correct aggregation: sum of revenues
correct_total = df_retail['Revenue'].sum()
print('Incorrect: sum of prices =', incorrect_total)
print('Correct: sum of revenue =', correct_total)
Incorrect: sum of prices = 2498821.9739999995
Correct: sum of revenue = 9747765.934

Error Handling Example: Incorrect Grouping#

  • Grouping by only product or only category can lead to misleading comparisons.
  • Always ensure your groupby keys match your business question.
# Mistake: grouping by ProductID only (simulated) for category analysis
bad_category_group = retail_sample.groupby('ProductID')['Revenue'].sum()
# Better: group by Category
good_category_group = retail_sample.groupby('Category')['Revenue'].sum()
print('By ProductID only (sample):', bad_category_group.head())
print('By Category (top):', good_category_group.sort_values(ascending=False).head())
By ProductID only (sample): ProductID
1001     89594.85
1002     97953.92
1003    100296.29
1004     97656.63
1005    102590.80
Name: Revenue, dtype: float64
By Category (top): Category
Sports         2425686.753
Clothing       2284072.041
Beauty         1863810.950
Electronics    1686586.110
Home           1487610.080
Name: Revenue, dtype: float64

Best Practices in Retail Analytics#

  • Segment customers by revenue, frequency, and product mix for tailored marketing.
  • Monitor product performance to optimize inventory and pricing.
  • Use basket analysis for cross-selling. Forecast demand to stay ahead of trends.

Advanced Pattern: Monthly Revenue Growth Rate#

  • Measuring monthly growth rate gives visibility into business momentum.
  • Look for positive momentum or declines to plan tactical actions.
monthly_growth = monthly_revenue.pct_change().dropna()*100
print('Monthly revenue growth rate (%):')
print(monthly_growth.round(1).head())
Monthly revenue growth rate (%):
Month
2011-01   -25.2
2011-02   -11.1
2011-03    37.2
2011-04   -27.8
2011-05    46.7
Freq: M, Name: Revenue, dtype: float64

Advanced Pattern: Detecting Seasonal Trends#

  • Retail businesses often see repeating seasonal patterns.
  • Visualizing or quantifying these helps with stock and staff planning.
# Calculate average revenue by month of year
df_retail['MonthNum'] = df_retail['InvoiceDate'].dt.month
avg_by_month = df_retail.groupby('MonthNum')['Revenue'].mean()
print('Average revenue per month of year:')
print(avg_by_month.round(2))
Average revenue per month of year:
MonthNum
1     15.93
2     17.98
3     18.59
4     16.49
5     19.53
6     18.74
7     17.24
8     19.35
9     20.30
10    17.63
11    17.26
12    17.39
Name: Revenue, dtype: float64

End-to-End Retail Analytics Example#

  • Let us combine our knowledge to answer a real business question:
  • "Which products and customers generated the most revenue last quarter?"
# Identify last quarter's timeframe
latest_date = df_retail['InvoiceDate'].max()
quarter = (df_retail['InvoiceDate'] > (latest_date - pd.Timedelta(days=90)))
df_q = df_retail[quarter]
# Top products by revenue
prod_q = df_q.groupby('Description')['Revenue'].sum().sort_values(ascending=False).head(5)
print('Top 5 products last quarter by revenue:')
print(prod_q)
# Top customers by revenue
cust_q = df_q.groupby('Customer ID')['Revenue'].sum().sort_values(ascending=False).head(5)
print('Top 5 customers last quarter by revenue:')
print(cust_q)
Top 5 products last quarter by revenue:
Description
DOTCOM POSTAGE                     85834.48
RABBIT NIGHT LIGHT                 56727.59
PAPER CHAIN KIT 50'S CHRISTMAS     50193.49
REGENCY CAKESTAND 3 TIER           38283.00
JUMBO BAG RED RETROSPOT            29572.22
Name: Revenue, dtype: float64
Top 5 customers last quarter by revenue:
Customer ID
18102.0    124206.55
17450.0    103091.11
14646.0    101903.40
14911.0     60507.06
14096.0     57017.25
Name: Revenue, dtype: float64

Lesson Wrap-Up#

  • You learned how to analyze retail sales, customers, products, and time trends.
  • Strong retail analytics drives smarter decisions in pricing, marketing, and operations.
  • Explore more advanced topics and practice on new datasets.
  • Subscribe to our YouTube for hands-on business analytics!

Found this useful?

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