Mathew K Analytics

Lesson 58 · Python for Retail E-commerce Analytics

Retail Sales Forecasting Case Study Training with Python for E-commerce Analytics

We will solve a real-world retail sales forecasting problem using Python. Forecasting future sales helps businesses plan inventory, marketing campaigns, and…

⬇ Download notebookOpen in Colab ↗

📓 Full notebook

Download .ipynb

Retail Sales Forecasting Case Study#

  • We will solve a real-world retail sales forecasting problem using Python.
  • Forecasting future sales helps businesses plan inventory, marketing campaigns, and staffing.
  • Accurate forecasts lead to better stock management, fewer lost sales, and higher profits.
  • By the end, you will learn to explore sales data, identify sales patterns, and build forecasting insights.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

Core Concepts in Retail Sales Analytics#

  • Retail datasets record each product sale, customer, date, quantity, and price.
  • Common metrics: sales revenue, units sold, average transaction value.
  • Grouping data by product, customer, or date reveals valuable patterns.
  • Beginners often forget to multiply quantity by price for total revenue.
  • Time is essential: trends can shift with seasons, holidays, or promotions.
# Loading UCI Online Retail Transactions dataset for sales analysis
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 1: Calculate Total Sales Revenue#

  • Calculate total revenue by multiplying quantity and price for each line item.
  • Sum this value across all transactions to get total sales.
df['LineRevenue'] = df['Quantity'] * df['Price']
total_revenue = df['LineRevenue'].sum()
print(f"Total sales revenue: {total_revenue:,.2f}")
Total sales revenue: 9,747,765.93

Beginner Example 2: Identify Top-Selling Products#

  • Group sales by product, summing revenue for each item.
  • Find the products with the highest total revenue.
top_products = df.groupby('Description')['LineRevenue'].sum().sort_values(ascending=False).head(5)
print('Top 5 products by revenue:')
print(top_products)
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

Beginner Example 3: Daily Sales Revenue Trend#

  • Sum daily total revenue over time.
  • Visualize to spot trends and volatility.
daily_revenue = df.groupby(df['InvoiceDate'].dt.date)['LineRevenue'].sum()
daily_revenue.plot(figsize=(12,5))
plt.title('Daily Sales Revenue Trend')
plt.ylabel('Revenue (GBP)')
plt.xlabel('Date')
plt.tight_layout()
plt.show()
No description has been provided for this image

Intermediate Example 1: Average Order Value (AOV)#

  • Calculate AOV by dividing total revenue by number of unique invoices.
  • A higher AOV often means more efficient sales and higher profitability.
n_invoices = df['Invoice'].nunique()
aov = total_revenue / n_invoices
print(f"Average Order Value (AOV): {aov:,.2f}")
Average Order Value (AOV): 376.36

Intermediate Example 2: Customer Analysis Who Are the Biggest Buyers?#

  • Group sales by customer, summing their total purchases.
  • Identify the customers who spend the most.
customer_sales = df.groupby('Customer ID')['LineRevenue'].sum().sort_values(ascending=False).head(5)
print('Top 5 customers by spend:')
print(customer_sales)
Top 5 customers by spend:
Customer ID
14646.0    279489.02
18102.0    256438.49
17450.0    187482.17
14911.0    132572.62
12415.0    123725.45
Name: LineRevenue, dtype: float64

Intermediate Example 3: Category Performance with Synthetic Product Catalog#

  • Use a synthetic catalog to assign categories and analyze revenue by category.
  • Find which categories drive the highest sales.
np.random.seed(42)
categories = ['Electronics','Clothing','Home','Sports','Beauty']
product_ids = df['StockCode'].drop_duplicates().sample(100, random_state=42)
product_categories = np.random.choice(categories, 100)
synthetic_catalog = pd.DataFrame({'StockCode': product_ids.values, 'Category': product_categories})
df_cat = df.merge(synthetic_catalog, on='StockCode', how='left')
cat_sales = df_cat.groupby('Category')['LineRevenue'].sum().sort_values(ascending=False)
print('Revenue by product category (synthetic):')
print(cat_sales)
Revenue by product category (synthetic):
Category
Sports         57009.65
Clothing       41356.00
Beauty         35732.85
Electronics    35485.80
Home           17142.32
Name: LineRevenue, dtype: float64

Advanced Example 1: Weekly Sales Forecasting with a Simple Model#

  • Aggregate sales by week to see longer patterns.
  • Use previous weeks' sales as a naive baseline forecast.
weekly_revenue = df.groupby(df['InvoiceDate'].dt.to_period('W'))['LineRevenue'].sum()
forecast = weekly_revenue.shift(1)
actual_vs_forecast = pd.DataFrame({'Actual': weekly_revenue, 'Forecast': forecast})
print(actual_vs_forecast.tail())
                          Actual   Forecast
InvoiceDate                                
2011-11-07/2011-11-13  346560.14  288266.77
2011-11-14/2011-11-20  380407.57  346560.14
2011-11-21/2011-11-27  308185.02  380407.57
2011-11-28/2011-12-04  319874.99  308185.02
2011-12-05/2011-12-11  300623.22  319874.99

Advanced Example 2: Visualizing Actual vs Forecasted Sales#

  • Plot both actual and forecasted weekly sales to evaluate forecasting accuracy.
  • Spot where the forecast lags or spikes unexpectedly.
actual_vs_forecast.plot(figsize=(12,5), marker='o')
plt.title('Weekly Actual vs. Forecasted Sales Revenue')
plt.ylabel('Revenue (GBP)')
plt.xlabel('Week')
plt.legend(['Actual', 'Forecast'])
plt.tight_layout()
plt.show()
No description has been provided for this image

Advanced Example 3: Handle Missing Values in Sales Data#

  • Missing prices or quantities can produce incorrect totals.
  • Fill missing values or drop invalid rows for accurate analysis.
missing = df[['Quantity', 'Price']].isnull().sum()
print('Missing values in Quantity and Price:')
print(missing)
df_clean = df.dropna(subset=['Quantity','Price'])
print(f'After cleaning: {df_clean.shape[0]} rows')
Missing values in Quantity and Price:
Quantity    0
Price       0
dtype: int64
After cleaning: 541910 rows

Error Example 1: Incorrect Revenue Calculation#

  • Multiplying only price or only quantity leads to wrong results.
  • Always check the formula for total revenue.
wrong_revenue = df['Price'].sum()
print(f"Incorrect revenue calculation (price sum only): {wrong_revenue:,.2f}")
Incorrect revenue calculation (price sum only): 2,498,821.97

Error Example 2: Wrong Grouping for Category Sales#

  • Grouping by wrong column can give misleading results.
  • Always group by logical business keys (category, customer, product).
wrong_group = df_cat.groupby('Invoice')['LineRevenue'].sum().head(3)
print('Grouping by Invoice shows sales per transaction, not per category:')
print(wrong_group)
Grouping by Invoice shows sales per transaction, not per category:
Invoice
536365    139.12
536366     22.20
536367    278.73
Name: LineRevenue, dtype: float64

Best Practices for Reliable Retail Sales Analytics#

  • Always check for missing values and outliers.
  • Double-check your formulas and groupings.
  • Use multiple time periods (day, week, month) for sales trends.
  • Segment customers and products for deeper insights.
  • Test different forecasting methods, even simple ones.
  • Document every step for stakeholder transparency.

Practice: End-to-End Problem Find Top 3 Products with Most Seasonal Uplift#

  • Calculate average monthly revenue for each product.
  • Find products with largest difference between peak and lowest month.
  • Recommend these to be prioritized for seasonal campaigns.
df['Month'] = df['InvoiceDate'].dt.to_period('M')
monthly_prod_rev = df.groupby(['Description','Month'])['LineRevenue'].sum().reset_index()
pivot = monthly_prod_rev.pivot(index='Description', columns='Month', values='LineRevenue').fillna(0)
peak_diff = pivot.max(axis=1) - pivot.min(axis=1)
top_seasonal = peak_diff.sort_values(ascending=False).head(3)
print('Top 3 products with largest seasonal revenue shifts:')
print(top_seasonal)
Top 3 products with largest seasonal revenue shifts:
Description
Manual                            40943.33
PICNIC BASKET WICKER 60 PIECES    39619.50
AMAZON FEE                        39243.08
dtype: float64
 

Found this useful?

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