Mathew K Analytics

Lesson 3 · Python for Retail E-commerce Analytics

Understanding Types of Retail and E-commerce Data for Effective Python Analytics

In this lesson, we will explore how to work with real-world retail and e-commerce data to answer important business questions. Understanding these datasets…

⬇ 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

Types of Retail and E-commerce Data#

  • In this lesson, we will explore how to work with real-world retail and e-commerce data to answer important business questions.
  • Understanding these datasets enables organizations to optimize sales, improve marketing, and make smarter inventory decisions.
  • Our goal is to analyze the core data types in retail to uncover patterns in transactions, customer behavior, product performance, and sales trends.
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')

Understanding Core Retail and E-commerce Data Types#

  • Retail datasets typically include transactions, product catalogs, customer profiles, and sales records.
  • Metrics like revenue, quantity, and price are structured in columns and rows, where each row is a specific record (such as a transaction or product).
  • Common beginner mistakes include misreading column meanings, aggregating the wrong way, or ignoring missing data.
# Example: Loading an online retail transactions dataset
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00502/online_retail_II.xlsx'
df_transactions = pd.read_excel(url, sheet_name='Year 2010-2011')
df_transactions['InvoiceDate'] = pd.to_datetime(df_transactions['InvoiceDate'])
print(df_transactions.shape)
print(df_transactions.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 1: Basic Transaction Exploration#

  • Let us review the key columns in our retail transactions dataset: Invoice, StockCode, Description, Quantity, InvoiceDate, Price, Customer ID, Country.
print('Columns:', list(df_transactions.columns))
Columns: ['Invoice', 'StockCode', 'Description', 'Quantity', 'InvoiceDate', 'Price', 'Customer ID', 'Country']
# Beginner Example 2: Counting Transactions per Country
trans_per_country = df_transactions['Country'].value_counts().head(5)
print(trans_per_country)
Country
United Kingdom    495478
Germany             9495
France              8558
EIRE                8196
Spain               2533
Name: count, dtype: int64
# Beginner Example 3: Simple Sales Revenue Calculation
df_transactions['Revenue'] = df_transactions['Quantity'] * df_transactions['Price']
total_revenue = df_transactions['Revenue'].sum()
print('Total Revenue:', round(total_revenue,2))
Total Revenue: 9747765.93
# Intermediate Example 1: Analyze Unique Customers
n_customers = df_transactions['Customer ID'].nunique()
print('Unique Customers:', n_customers)
Unique Customers: 4372
# Intermediate Example 2: Top Selling Products by Quantity
top_products = df_transactions.groupby('Description')['Quantity'].sum().sort_values(ascending=False).head(5)
print(top_products)
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
# Intermediate Example 3: Average Order Value
avg_order_value = df_transactions.groupby('Invoice')['Revenue'].sum().mean()
print('Average Order Value:', round(avg_order_value,2))
Average Order Value: 376.36
# Intermediate Example 4: Sales Over Time - Monthly Trend
monthly_sales = df_transactions.resample('M', on='InvoiceDate')['Revenue'].sum()
print(monthly_sales.head())
InvoiceDate
2010-12-31    748957.020
2011-01-31    560000.260
2011-02-28    498062.650
2011-03-31    683267.080
2011-04-30    493207.121
Freq: ME, Name: Revenue, dtype: float64
# Intermediate Example 5: Customers with Most Transactions
top_customers = df_transactions['Customer ID'].value_counts().head(5)
print(top_customers)
Customer ID
17841.0    7983
14911.0    5903
14096.0    5128
12748.0    4642
14606.0    2782
Name: count, dtype: int64
# Advanced Example 1: Market Basket Data Setup
products = ['Bread','Milk','Butter','Eggs','Apples','Chicken','Rice','Cheese']
transaction_ids = np.repeat(np.arange(1,301),3)
np.random.seed(42)
product_choices = np.random.choice(products,len(transaction_ids))
df_basket = pd.DataFrame({'TransactionID':transaction_ids,'Product':product_choices})
print(df_basket.head(3))
   TransactionID Product
0              1    Rice
1              1    Eggs
2              1  Apples
# Advanced Example 2: Counting Basket Product Frequencies
basket_counts = df_basket['Product'].value_counts()
print(basket_counts)
Product
Eggs       127
Cheese     122
Bread      121
Apples     110
Rice       109
Milk       106
Butter     103
Chicken    102
Name: count, dtype: int64
# Advanced Example 3: Cross-Sell Product Pairs
cross_sell = df_basket.groupby('TransactionID')['Product'].apply(list)
from itertools import combinations
from collections import Counter
pair_counts = Counter()
for basket in cross_sell:
    for pair in combinations(sorted(basket), 2):
        pair_counts[pair] += 1
top_pairs = pair_counts.most_common(5)
print(top_pairs)
[(('Apples', 'Eggs'), 41), (('Bread', 'Eggs'), 41), (('Cheese', 'Rice'), 36), (('Eggs', 'Milk'), 36), (('Butter', 'Cheese'), 35)]
# Advanced Example 4: Setting Up a Product Catalog
categories = ['Electronics','Clothing','Home','Sports','Beauty']
product_ids = list(range(1001,1101))
np.random.seed(42)
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.head(3))
   ProductID Category   Price
0       1001   Sports  457.91
1       1002   Beauty  425.77
2       1003     Home  227.48
# Advanced Example 5: Category Revenue Calculation
merged = pd.merge(df_transactions, df_catalog, left_on='StockCode', right_on='ProductID', how='inner')
category_revenue = merged.groupby('Category')['Revenue'].sum().sort_values(ascending=False)
print(category_revenue)
Series([], Name: Revenue, dtype: float64)
# Advanced Example 6: Simulated Customer Orders 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')
df_orders = pd.DataFrame({'OrderID':order_ids,'CustomerID':customer_ids,'ProductID':product_ids,'Quantity':quantities,'OrderDate':order_dates})
print(df_orders.head(3))
   OrderID  CustomerID  ProductID  Quantity           OrderDate
0        1        1102       1049         3 2023-01-01 00:00:00
1        2        1435       1011         1 2023-01-01 01:00:00
2        3        1348       1085         3 2023-01-01 02:00:00
# Error Handling Example 1: Checking for Missing Values
missing_counts = df_transactions.isnull().sum()
print(missing_counts[missing_counts > 0])
Description      1454
Customer ID    135080
dtype: int64
# Error Handling Example 2: Catching Incorrect Aggregations
incorrect_sum = df_transactions['Quantity'].sum()
print('Sum of Quantities:', incorrect_sum)
correct_sum = df_transactions[df_transactions['Quantity'] > 0]['Quantity'].sum()
print('Correct (Excluding Returns):', correct_sum)
Sum of Quantities: 5176451
Correct (Excluding Returns): 5660982
# Error Handling Example 3: Mistaken Grouping by Product
wrong_group = df_transactions.groupby('StockCode')['Revenue'].sum().head(3)
correct_group = df_transactions.groupby('Description')['Revenue'].sum().head(3)
print('By StockCode:', wrong_group)
print('By Description:', correct_group)
By StockCode: StockCode
10002    759.89
10080    119.09
10120     40.53
Name: Revenue, dtype: float64
By Description: Description
20713                                0.00
 4 PURPLE FLOCK DINNER CANDLES     290.80
 50'S CHRISTMAS GIFT BAG LARGE    2341.13
Name: Revenue, dtype: float64
# Error Handling Example 4: Misinterpreting Revenue Calculation
df_transactions['FakeRevenue'] = df_transactions['Price']
fake_sum = df_transactions['FakeRevenue'].sum()
true_sum = df_transactions['Revenue'].sum()
print('Fake Revenue:', fake_sum)
print('True Revenue:', true_sum)
Fake Revenue: 2498821.9739999995
True Revenue: 9747765.934

Best Practices and Retail Analytics Patterns#

  • Always cross-check product and customer identifiers before grouping or merging datasets.
  • Use product catalogs for richer product-level analysis.
  • Identify high-value customers using total spending or frequency of purchase.
  • Apply market basket analysis to identify products that sell well together.
  • Incorporate time-based analyses to spot trends and forecast demand.
# Pattern: High-Value Customer Segmentation
customer_rev = df_transactions.groupby('Customer ID')['Revenue'].sum().sort_values(ascending=False)
vip_customers = customer_rev[customer_rev > customer_rev.quantile(0.95)]
print(vip_customers)
Customer ID
14646.0    279489.02
18102.0    256438.49
17450.0    187482.17
14911.0    132572.62
12415.0    123725.45
             ...    
13050.0      5684.61
14110.0      5669.65
16553.0      5664.57
13468.0      5656.75
14049.0      5639.15
Name: Revenue, Length: 219, dtype: float64
# Pattern: Product Performance by Category
category_perf = merged.groupby('Category').agg({'Revenue': 'sum', 'Quantity':'sum'})
print(category_perf)
Empty DataFrame
Columns: [Revenue, Quantity]
Index: []
# Pattern: Demand Forecasting using Recent Sales
recent_sales = df_transactions.set_index('InvoiceDate').last('30D')['Revenue'].resample('D').sum()
print(recent_sales.head())
InvoiceDate
2011-11-09    30894.91
2011-11-10    68956.24
2011-11-11    54835.51
2011-11-12        0.00
2011-11-13    33520.22
Freq: D, Name: Revenue, dtype: float64

Tiny End-to-End Problem: Finding Top-Selling Products for Next Month's Promotion#

  • We want to recommend the two best-selling products from all past orders for a new store promotion.
  • This means calculating sales by product, ranking the products, and suggesting the top performers.
top2 = df_transactions.groupby('Description')['Revenue'].sum().nlargest(2)
print('Recommended for promotion:')
print(top2)
Recommended for promotion:
Description
DOTCOM POSTAGE              206245.48
REGENCY CAKESTAND 3 TIER    164762.19
Name: Revenue, dtype: float64

Well Done! Key Takeaways#

  • You now understand the key types of retail and e-commerce data and how to explore them in Python.
  • You can identify sales trends, customer behavior, and product performance for real business impact.
  • Practice these examples on your own retail datasets to gain true business insight.

Found this useful?

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