Mathew K Analytics

Lesson 21 · Python for Retail E-commerce Analytics

Descriptive Statistics for Retail Data Analysis in Python

In this lesson, you will learn how to use descriptive statistics to analyze retail and e-commerce datasets. Descriptive statistics help retail teams…

⬇ Download notebookOpen in Colab ↗

📓 Full notebook

Download .ipynb

Descriptive Statistics for Retail Data#

  • In this lesson, you will learn how to use descriptive statistics to analyze retail and e-commerce datasets.
  • Descriptive statistics help retail teams understand sales patterns, customer behaviors, and product performance.
  • You will produce actionable insights such as average order value, best-selling products, and customer purchasing trends.
  • These skills are essential for making data-driven sales, marketing, and inventory decisions.
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')

Understanding Retail Analytics Data#

  • Retail datasets reflect business activities: transactions, customer orders, product catalogs, and more.
  • Transactions often describe individual purchases, including product codes, prices, and quantities.
  • Key sales metrics include revenue, quantity sold, price, and customer details.
  • Common mistakes include confusing total revenue with quantity, or grouping data incorrectly by product or category.
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/00502/online_retail_II.xlsx'
retail_df = pd.read_excel(url, sheet_name='Year 2010-2011')
retail_df['InvoiceDate'] = pd.to_datetime(retail_df['InvoiceDate'])
print(retail_df.shape)
print(retail_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: Counting Unique Products#

  • Counting unique products helps identify assortment breadth.
  • Knowing how many different products customers buy affects inventory and marketing choices.
num_unique_products = retail_df['StockCode'].nunique()
print('Unique products sold:', num_unique_products)
Unique products sold: 4070

Beginner Example: Total Transactions#

  • Counting total transactions gives a sense of business scale.
  • This helps in understanding sales volumes and operational needs.
num_transactions = retail_df['Invoice'].nunique()
print('Total unique transactions (invoices):', num_transactions)
Total unique transactions (invoices): 25900

Beginner Example: Simple Revenue Calculation#

  • Revenue is a key metric for retail analysis.
  • Multiplying quantity by price for each line gives the basic revenue per purchase.
retail_df['LineRevenue'] = retail_df['Quantity'] * retail_df['Price']
total_revenue = retail_df['LineRevenue'].sum()
print('Total revenue (GBP): {:.2f}'.format(total_revenue))
Total revenue (GBP): 9747765.93

Intermediate Example: Average Order Value (AOV)#

  • Average order value helps understand typical customer spending behavior.
  • It is used to target promotions and set free shipping thresholds.
invoice_revenue = retail_df.groupby('Invoice')['LineRevenue'].sum()
avg_order_value = invoice_revenue.mean()
print('Average order value (GBP): {:.2f}'.format(avg_order_value))
Average order value (GBP): 376.36

Intermediate Example: Top-Selling Products#

  • Identifying top-selling products is critical for inventory planning.
  • It informs buyers of what drives revenue.
product_sales = retail_df.groupby('Description')['Quantity'].sum().sort_values(ascending=False)
print('Top 5 Products by Units Sold:')
print(product_sales.head(5))
Top 5 Products by Units Sold:
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: Product Revenue Analysis#

  • Some products sell in high volume but contribute less revenue.
  • This analysis shows which products generate the most money.
product_revenue = retail_df.groupby('Description')['LineRevenue'].sum().sort_values(ascending=False)
print('Top 5 Products by Revenue:')
print(product_revenue.head(5))
Top 5 Products by Revenue:
Description
DOTCOM POSTAGE                        206245.48
REGENCY CAKESTAND 3 TIER              164762.19
WHITE HANGING HEART T-LIGHT HOLDER     99668.47
PARTY BUNTING                          98302.98
JUMBO BAG RED RETROSPOT                92356.03
Name: LineRevenue, dtype: float64

Advanced Example: Sales by Country#

  • Retailers often sell internationally, so country-level insights support localization strategies.
  • Comparing revenues by country uncovers regional strengths and weaknesses.
country_revenue = retail_df.groupby('Country')['LineRevenue'].sum().sort_values(ascending=False)
print('Top 5 Countries by Revenue:')
print(country_revenue.head(5))
Top 5 Countries by Revenue:
Country
United Kingdom    8187806.364
Netherlands        284661.540
EIRE               263276.820
Germany            221698.210
France             197421.900
Name: LineRevenue, dtype: float64

Advanced Example: Monthly Revenue Trend Analysis#

  • Analyzing revenue trends over time reveals demand patterns and seasonality.
  • Identifying peaks and troughs guides marketing campaigns and inventory stocking.
retail_df['Month'] = retail_df['InvoiceDate'].dt.to_period('M')
monthly_revenue = retail_df.groupby('Month')['LineRevenue'].sum()
print(monthly_revenue.head())
Month
2010-12    748957.020
2011-01    560000.260
2011-02    498062.650
2011-03    683267.080
2011-04    493207.121
Freq: M, Name: LineRevenue, dtype: float64

Advanced Example: Average Items per Transaction#

  • Calculating items per transaction helps measure upselling and cross-selling success.
  • It also uncovers whether large baskets or single-item purchases are more common.
items_per_invoice = retail_df.groupby('Invoice')['Quantity'].sum()
avg_items_transaction = items_per_invoice.mean()
print('Average items per transaction: {:.2f}'.format(avg_items_transaction))
Average items per transaction: 199.86

Error Handling Example: Missing Values in Revenue#

  • Missing quantity or price leads to incorrect revenue calculations.
  • This is a common issue when analyzing real-world sales data.
missing_lines = retail_df[retail_df['Quantity'].isna() | retail_df['Price'].isna()]
print('Rows with missing Quantity or Price:', missing_lines.shape[0])
Rows with missing Quantity or Price: 0

Error Handling Example: Incorrect Revenue Aggregation#

  • Forgetting to group by invoice before summing revenue can inflate result totals.
  • Always check aggregation logic for business accuracy.
# Incorrect: Double counting by not grouping properly
incorrect_total = (retail_df.groupby('Invoice')['LineRevenue'].mean().sum())
print('Incorrect total if not grouping right: {:.2f}'.format(incorrect_total))
# Correct way for comparison
print('Correct total revenue (should match earlier): {:.2f}'.format(total_revenue))
Incorrect total if not grouping right: 524789.31
Correct total revenue (should match earlier): 9747765.93

Best Practices in Retail Analytics#

  • Use customer segmentation to tailor marketing and promotions.
  • Analyze product performance both in sales volume and revenue.
  • Apply market basket analysis to reveal common product pairings.
  • Use time trends (daily, weekly, monthly) to anticipate demand spikes.
  • Check for missing values or data outliers before reporting.

Advanced Practice: Customer Segmentation by Spend#

  • Segmenting customers by total spend lets you identify VIPs and regulars.
  • Focusing on top segments drives higher revenue per marketing dollar.
customer_spend = retail_df.groupby('Customer ID')['LineRevenue'].sum().dropna()
high_value_customers = customer_spend[customer_spend > customer_spend.quantile(0.95)]
print('Top 5% of customers by spend:', high_value_customers.shape[0])
Top 5% of customers by spend: 219

Advanced Practice: Product Category Performance (Using Synthetic Dataset)#

  • Analyzing performance by product category aids assortment planning.
  • Let us simulate a product catalog to show category analytics.
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_df = pd.DataFrame({'ProductID':product_ids,'Category':product_categories,'Price':product_prices})
print(catalog_df.head(3))
   ProductID Category   Price
0       1001   Sports  457.91
1       1002   Beauty  425.77
2       1003     Home  227.48

Intermediate Practice: Market Basket Transaction Simulation#

  • Simulating baskets reveals which products customers commonly buy together.
  • This is useful for cross-selling and product placement decisions.
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})
print(basket_df.head(3))
   TransactionID Product
0              1  Butter
1              1    Eggs
2              1   Bread

End-to-End Example: Find the Top 3 Revenue-Generating Products#

  • This small project takes raw retail transaction data to a clear answer.
  • Finding best sellers is crucial for promotions, supplier deals, and restocking priorities.
result = retail_df.groupby('Description')['LineRevenue'].sum().sort_values(ascending=False).head(3)
print('Top 3 revenue-generating products:')
for i, (desc, rev) in enumerate(result.items(), 1):
    print(f'{i}. {desc}: GBP {rev:.2f}')
Top 3 revenue-generating products:
1. DOTCOM POSTAGE: GBP 206245.48
2. REGENCY CAKESTAND 3 TIER: GBP 164762.19
3. WHITE HANGING HEART T-LIGHT HOLDER: GBP 99668.47

Practice Prompt#

  • Try to use what you have learned by modifying revenue calculations for specific months or products.
  • Explore further with other public datasets, and check out more analytics tips on our YouTube channel!

Found this useful?

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