Mathew K Analytics

Lesson 55 · Python for Retail E-commerce Analytics

Exporting Retail Analysis Reports Using Python for E-commerce Analytics

Learn how to aggregate and export real sales insights from retail data. Discover why exporting analysis is critical for business reporting and…

⬇ 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

Exporting Retail Analysis Reports#

  • Learn how to aggregate and export real sales insights from retail data.
  • Discover why exporting analysis is critical for business reporting and collaboration.
  • By the end, you will create, analyze, and export retail reports that support key decisions.
  • No advanced Python required. We will build practical, ready-to-export reports together.
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')

Key Retail Analytics Concepts for Reports#

  • Retail datasets include orders, products, transactions, and customers.
  • Key sales metrics: revenue, quantity, and price per product or order.
  • Common mistakes: summing quantities without grouping, or missing joined product details.
  • Retail reporting often summarizes data by date, customer, or product.
# Load the 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  
# Basic check for missing values
print(df_retail.isnull().sum())
Invoice             0
StockCode           0
Description      1454
Quantity            0
InvoiceDate         0
Price               0
Customer ID    135080
Country             0
dtype: int64
# Beginner: Aggregate total quantity and revenue per product
df_retail['Revenue'] = df_retail['Quantity'] * df_retail['Price']
prod_summary = df_retail.groupby('Description').agg({'Quantity': 'sum', 'Revenue': 'sum'}).reset_index()
print(prod_summary.head(5))
                      Description  Quantity  Revenue
0                           20713      -400     0.00
1   4 PURPLE FLOCK DINNER CANDLES       144   290.80
2   50'S CHRISTMAS GIFT BAG LARGE      1913  2341.13
3               DOLLY GIRL BEAKER      2448  2882.50
4     I LOVE LONDON MINI BACKPACK       389  1628.17
# Beginner: Sum total revenue across the entire dataset
total_revenue = df_retail['Revenue'].sum()
print(f'Total revenue: GBP {total_revenue:,.2f}')
Total revenue: GBP 9,747,765.93
# Beginner: Show monthly revenue trend (time-based analysis for reports)
df_retail['YearMonth'] = df_retail['InvoiceDate'].dt.to_period('M')
monthly_revenue = df_retail.groupby('YearMonth')['Revenue'].sum().reset_index()
print(monthly_revenue.head(6))
  YearMonth     Revenue
0   2010-12  748957.020
1   2011-01  560000.260
2   2011-02  498062.650
3   2011-03  683267.080
4   2011-04  493207.121
5   2011-05  723333.510
# Beginner: Export the product summary to a CSV file for reporting
prod_summary.to_csv('product_sales_summary.csv', index=False)
print('Product summary exported to product_sales_summary.csv')
Product summary exported to product_sales_summary.csv
# Beginner: Export the monthly revenue report as Excel (XLSX)
monthly_revenue.to_excel('monthly_revenue_report.xlsx', index=False)
print('Monthly revenue report exported as monthly_revenue_report.xlsx')
Monthly revenue report exported as monthly_revenue_report.xlsx
# Intermediate: Aggregate revenue by country for region-based reporting
country_rev = df_retail.groupby('Country')['Revenue'].sum().reset_index().sort_values('Revenue', ascending=False)
print(country_rev.head(5))
           Country      Revenue
36  United Kingdom  8187806.364
24     Netherlands   284661.540
10            EIRE   263276.820
14         Germany   221698.210
13          France   197421.900
# Intermediate: Calculate average order value (AOV) for business insight
df_retail['OrderRevenue'] = df_retail.groupby('Invoice')['Revenue'].transform('sum')
avg_order_value = df_retail[['Invoice', 'OrderRevenue']].drop_duplicates()['OrderRevenue'].mean()
print(f'Average order value: GBP {avg_order_value:,.2f}')
Average order value: GBP 376.36
# Intermediate: Export country revenue report for external sharing
country_rev.to_csv('country_revenue_summary.csv', index=False)
print('Country-wise revenue exported to country_revenue_summary.csv')
Country-wise revenue exported to country_revenue_summary.csv
# Intermediate: Create a simple Excel report with multiple sheets
with pd.ExcelWriter('retail_comprehensive_report.xlsx') as writer:
    prod_summary.to_excel(writer, sheet_name='Product_Summary', index=False)
    monthly_revenue.to_excel(writer, sheet_name='Monthly_Revenue', index=False)
    country_rev.to_excel(writer, sheet_name='Country_Revenue', index=False)
print('Retail comprehensive report exported as retail_comprehensive_report.xlsx')
Retail comprehensive report exported as retail_comprehensive_report.xlsx
# Intermediate: Identify and export top 10 high-value customers
cust_rev = df_retail.groupby('Customer ID')['Revenue'].sum().reset_index()
top_customers = cust_rev.sort_values('Revenue', ascending=False).head(10)
top_customers.to_csv('top_10_customers.csv', index=False)
print(top_customers)
      Customer ID    Revenue
1703      14646.0  279489.02
4233      18102.0  256438.49
3758      17450.0  187482.17
1895      14911.0  132572.62
55        12415.0  123725.45
1345      14156.0  113384.14
3801      17511.0   88125.38
3202      16684.0   65892.08
1005      13694.0   62653.10
2192      15311.0   59419.34
# Advanced: Export filtered product report (only electronics category example)
electronics = prod_summary[prod_summary['Description'].str.contains('electronic', case=False, na=False)]
electronics.to_csv('electronics_sales_summary.csv', index=False)
print(electronics.head(3))
                     Description  Quantity  Revenue
1121  Dad's Cab Electronic Meter         2    16.94
# Advanced: Export summary with formatted Excel columns for professional look
with pd.ExcelWriter('formatted_product_report.xlsx', engine='xlsxwriter') as writer:
    prod_summary.to_excel(writer, sheet_name='Summary', index=False)
    workbook  = writer.book
    worksheet = writer.sheets['Summary']
    money_fmt = workbook.add_format({'num_format': 'GBP #,##0.00'})
    worksheet.set_column('B:B', 10)
    worksheet.set_column('C:C', 18, money_fmt)
print('Formatted Excel export complete')
Formatted Excel export complete
# Advanced: Export top products to PDF using pandas and reportlab
from pandas.plotting import table
import matplotlib.pyplot as plt
top_products = prod_summary.sort_values('Revenue', ascending=False).head(10)
fig, ax = plt.subplots(figsize=(8, 4))
ax.xaxis.set_visible(False)  # Hide axes
ax.yaxis.set_visible(False)
ax.set_frame_on(False)
tbl = table(ax, top_products, loc='center', colWidths=[0.20]*len(top_products.columns))
tbl.auto_set_font_size(False)
tbl.set_fontsize(9)
plt.savefig('top_products_report.pdf', bbox_inches='tight')
plt.close()
# Error handling: Detect missing Customer IDs when exporting reports
missing_cust = df_retail['Customer ID'].isnull().sum()
if missing_cust > 0:
    print(f'Warning: {missing_cust} sales records are missing Customer ID and will be excluded from customer reporting.')
else:
    print('No missing Customer IDs detected.')
Warning: 135080 sales records are missing Customer ID and will be excluded from customer reporting.
# Error handling: Prevent wrong grouping in product export
bad_group_test = df_retail.agg({'Quantity':'sum', 'Revenue':'sum'})
print('Total Quantity (no product breakdown):', bad_group_test['Quantity'])
print('Total Revenue (no product breakdown): GBP', bad_group_test['Revenue'])
# This does not give a product report! Always group by product for per-product insights.
Total Quantity (no product breakdown): 5176451.0
Total Revenue (no product breakdown): GBP 9747765.934
# Error handling: Catch and report missing Price or Quantity when calculating revenue
missing_price = df_retail['Price'].isnull().sum()
missing_qty = df_retail['Quantity'].isnull().sum()
if missing_price > 0 or missing_qty > 0:
    print(f'Warning: {missing_price} records missing Price, {missing_qty} missing Quantity. These are excluded from revenue calculations.')
else:
    print('No missing Price or Quantity. Revenue calculation is complete and reliable.')
No missing Price or Quantity. Revenue calculation is complete and reliable.

Best Practices for Retail Report Exports#

  • Always check for missing values before exporting reports.
  • Group by relevant columns to produce actionable insights.
  • Format exported files for clarity (e.g., currency, dates).
  • Use descriptive file names and sheet names.
  • Run periodic checks for common data errors.
  • Share Excel or PDF files for better team communication.

Common Retail Analytics Patterns for Reports#

  • Customer segmentation: Export groups by purchase frequency or total spend.
  • Product performance: List top and bottom performers.
  • Market basket: Present paired product sales in exports.
  • Demand forecasting: Share trend reports using time-based exports.
  • Seasonal analysis: Export seasonal charts or sales tables.
# End-to-end problem: Identify top 5 products this quarter and export report
qtr = df_retail[df_retail['InvoiceDate'].dt.quarter == 1]
qtr_prod = qtr.groupby('Description').agg({'Quantity':'sum','Revenue':'sum'}).reset_index()
top5_qtr = qtr_prod.sort_values('Revenue', ascending=False).head(5)
top5_qtr.to_csv('Q1_top5_product_report.csv', index=False)
print(top5_qtr)
                             Description  Quantity   Revenue
2174            REGENCY CAKESTAND 3 TIER      3114  39039.14
827                       DOTCOM POSTAGE       185  35808.81
2830  WHITE HANGING HEART T-LIGHT HOLDER      9386  25928.01
1377             JUMBO BAG RED RETROSPOT     10998  20598.92
1815                       PARTY BUNTING      3072  15734.53
 

Found this useful?

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