Module 12 · Python for Data Analytics
"Final project: customer health review"
Plan and start your final project, a customer health review for Kolanut Distribution. Find which customers are growing, which are slipping, and what's really behind the North West's fall.
About 20 minutes
The problem
The board has seen Bisi's headline (lesson 9): North West revenue fell 47% from H1 2025 to H1 2026. The managing director's follow-up is the kind of question a final project should answer:
"Is the North West problem the whole region, or a few customers? And across the business: who's growing, who's slipping, and who should the sales team call this week?"
This lesson sets up the project and gets you started on it. The project itself is submitted from the course page; its brief lists exactly what to hand in.
The concept
Customer health: recency, frequency, value
A simple, widely used way to judge customers is RFM:
- Recency: days since their last order. A customer who hasn't ordered for two months is at risk, however much they spent last year.
- Frequency: how many orders they've placed.
- Monetary value: how much revenue they've brought in.
Each is one groupby on the orders. Together they say who's healthy and who's slipping.
Change per customer
The same H1-against-H1 comparison you made for regions in lesson 9 works per customer: a pivot table of revenue by customer and year, plus a change column. Sorting by change lists the biggest fallers first. Merging in customer details shows who they are and where.
Explaining a total with its parts
When a region falls, ask how much of the fall comes from its biggest movers. If two customers account for most of it, the fix is two phone calls, not a regional strategy.
A notebook someone else can follow
Structure the project notebook the way a reader thinks:
- Question (text cell): what you were asked, in your own words.
- Data and checks: load, merge with
validate, row counts, missing values. - Analysis: one section per sub-question, each ending in a sentence that says what the result shows.
- Charts: two or three, each with an action title.
- Findings and recommendations, with caveats.
It must run from top to bottom with Runtime → Run all.
Example
The starting point: recency, frequency and value for every customer.
import pandas as pd
base = "https://academy.cloudtechanalytics.com/datasets/sales/"
orders = pd.read_csv(base + "orders.csv", parse_dates=["order_date"])
customers = pd.read_csv(base + "customers.csv")
orders["revenue"] = orders["quantity"] * orders["unit_price"] * (1 - orders["discount_pct"] / 100)
as_of = orders["order_date"].max()
rfm = orders.groupby("customer_id").agg(
last_order=("order_date", "max"),
orders=("order_id", "nunique"),
revenue=("revenue", "sum"),
)
rfm["days_since"] = (as_of - rfm["last_order"]).dt.days
rfm = rfm.merge(customers, on="customer_id", how="left", validate="one_to_one")
print(f"Data ends {as_of:%d %B %Y}")
rfm.sort_values("days_since", ascending=False)[["customer_name", "region", "channel", "days_since", "revenue"]].head()And the change per customer from H1 2025 to H1 2026:
h1 = orders[orders["order_date"].dt.month <= 6].assign(year=lambda d: d["order_date"].dt.year)
change = h1.pivot_table(index="customer_id", columns="year", values="revenue", aggfunc="sum", fill_value=0)
change["change"] = change[2026] - change[2025]
change = change.merge(customers, on="customer_id", validate="one_to_one").sort_values("change")
change[["customer_name", "region", "channel", 2025, 2026, "change"]].head(3)customer_name region channel 2025 2026 change
57 Grace Wholesale North West Wholesale 9352695.0 2680855.0 -6671840.0
15 Olumide Wholesale North West Wholesale 9295740.0 3087875.0 -6207865.0
61 Divine Wholesale South East Wholesale 13566690.0 9439740.0 -4126950.0assign(year=lambda d: ...) adds a column inside a chain of steps: d is the table at that point.
The top two fallers are both North West wholesalers. That's where your project starts.
Walkthrough
- Create a new notebook named
Kolanut customer health reviewand add the five section headings above as text cells. - Run the Example's first cell under Data and checks, and add the checks: row counts before and after the merge, and
rfm.isna().sum(). - Recency: how many customers haven't ordered in the last 30 days?
(rfm["days_since"] > 30).sum(). - Run the change-per-customer cell. Then work out how much of the North West's fall comes from its two biggest fallers: filter
changeto North West and compare the sum of the two most negative rows with the region's total change. - Draw a bar chart of the 10 biggest fallers and the 10 biggest growers (
pd.concat([change.head(10), change.tail(10)]), then.plot.barh), with an action title. - Write a first draft of your findings, then open the project brief on the course page and check every task is covered.
Practice
Warm-ups that check your set-up before you start the project.
Practice
How many customers have not ordered for more than 30 days by the end of the data (30 June 2026)?
Practice
How many customers had lower revenue in H1 2026 than in H1 2025?
Practice
What percentage of the North West's total H1 fall comes from its two biggest fallers? Round to a whole number.
Check your understanding
Answer every question to check.