Lesson 7 · Pandas Projects
Retail Sales Analysis with Pandas: Find Trends & KPIs in Python
A complete, standalone tutorial: build a synthetic retail transactions dataset, then explore, clean, and analyze it with pandas. No prior pandas experience…
- CoursePandas Projects
- Lesson7 of 10
- Video21 min
- FormatJupyter notebook · 21 code cells
What you'll learn
Data
No separate download needed — the notebook creates or downloads everything it uses.
📓 Full notebook
Download .ipynbPandas for Retail: Analyzing Store Sales Data#
- A complete, standalone tutorial: build a synthetic retail transactions dataset, then explore, clean, and analyze it with pandas.
- No prior pandas experience needed. Let's jump straight in.
Before You Start#
- Open a new Jupyter Notebook in VS Code and select your Python interpreter as the kernel.
- If pandas isn't installed yet, open a terminal in VS Code and run: pip install pandas
Part 1: Building the Dataset#
import pandas as pd
import numpy as np
print(pd.__version__)
Generating Synthetic Sales Data#
rng = np.random.default_rng(seed=11)
stores = ['Downtown', 'Westside', 'Northgate', 'Eastview']
category_products = {
'Grocery': ['Bread', 'Milk', 'Eggs', 'Coffee', 'Rice'],
'Electronics': ['Headphones', 'Charger', 'Mouse', 'Webcam'],
'Apparel': ['T-Shirt', 'Jeans', 'Jacket', 'Socks'],
'Home & Garden': ['Lamp', 'Planter', 'Rug', 'Tool Kit'],
'Toys': ['Puzzle', 'Board Game', 'Action Figure']
}
categories = list(category_products.keys())
print(stores)
print(categories)
n_rows = 400
dates = pd.date_range('2026-01-01', periods=90, freq='D')
rows = []
for _ in range(n_rows):
date = rng.choice(dates)
store = rng.choice(stores)
category = rng.choice(categories)
product = rng.choice(category_products[category])
quantity = int(rng.integers(1, 6))
unit_price = round(float(rng.uniform(3, 120)), 2)
rows.append([date, store, category, product, quantity, unit_price])
sales = pd.DataFrame(rows, columns=['date', 'store', 'category', 'product', 'quantity', 'unit_price'])
sales.insert(0, 'order_id', range(1001, 1001 + len(sales)))
print(sales.shape)
sales.to_csv('retail_transactions.csv', index=False)
sales = pd.read_csv('retail_transactions.csv', parse_dates=['date'])
sales.head()
Part 2: First Look at the Data#
print(sales.shape)
print(sales.dtypes)
sales.info()
sales.describe()
sales['store'].value_counts()
Part 3: Deriving Revenue#
sales['revenue'] = sales['quantity'] * sales['unit_price']
sales[['product', 'quantity', 'unit_price', 'revenue']].head()
print(f"Total revenue: ${sales['revenue'].sum():,.2f}")
print(f"Average order value: ${sales['revenue'].mean():,.2f}")
Filtering and Sorting#
big_orders = sales[sales['revenue'] > 300]
print(len(big_orders))
big_orders.sort_values('revenue', ascending=False).head()
electronics_orders = sales[(sales['category'] == 'Electronics') & (sales['store'] == 'Downtown')]
electronics_orders.head()
Part 4: Grouping and Aggregating#
revenue_by_category = sales.groupby('category')['revenue'].sum().sort_values(ascending=False)
revenue_by_category
revenue_by_store = sales.groupby('store')['revenue'].sum().sort_values(ascending=False)
revenue_by_store
Multiple Aggregations with agg()#
category_summary = sales.groupby('category').agg(
total_revenue=('revenue', 'sum'),
avg_unit_price=('unit_price', 'mean'),
orders=('revenue', 'count')
).sort_values('total_revenue', ascending=False)
category_summary
Pivot Table: Store by Category#
pivot = pd.pivot_table(sales, values='revenue', index='store', columns='category', aggfunc='sum', fill_value=0)
pivot
Top Products#
top_products = sales.groupby('product')['revenue'].sum().nlargest(5)
top_products
Part 5: Trends Over Time#
daily_revenue = sales.groupby('date')['revenue'].sum()
print(daily_revenue.head())
print(daily_revenue.sort_values(ascending=False).head(3))
rolling_avg = daily_revenue.rolling(window=7).mean()
print(rolling_avg.tail())
Part 6: Visualizing the Results#
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(8, 5))
revenue_by_category.plot(kind='bar', ax=ax, color='steelblue')
ax.set_title('Total Revenue by Category')
ax.set_ylabel('Revenue ($)')
plt.tight_layout()
plt.savefig('revenue_by_category.png', dpi=150)
plt.close(fig)
print('Saved revenue_by_category.png')
fig, ax = plt.subplots(figsize=(9, 5))
daily_revenue.plot(ax=ax, color='gray', alpha=0.5, label='Daily revenue')
rolling_avg.plot(ax=ax, color='crimson', linewidth=2, label='7-day rolling average')
ax.set_title('Daily Revenue with 7-Day Rolling Average')
ax.set_ylabel('Revenue ($)')
ax.legend()
plt.tight_layout()
plt.savefig('daily_revenue_trend.png', dpi=150)
plt.close(fig)
print('Saved daily_revenue_trend.png')
Wrap-Up: What You Learned#
- Generating a realistic synthetic dataset with NumPy, then saving and reloading it with to_csv and read_csv.
- First-look exploration: shape, dtypes, info, describe, and value_counts.
- Deriving new columns, filtering with boolean conditions, and sorting.
- groupby, multi-statistic agg, and pivot_table for real business summaries.
- Time-based grouping and a rolling average to reveal trends.
- Saving clean, presentation-ready charts with matplotlib.
- You went from raw synthetic transactions to a full revenue analysis with charts. If you want the next dataset in this series to land in your feed automatically, subscribing is the move see you in the next one.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



