Mission M36 · Python · 35 min
RFM segmentation: find your Champions
Request from your manager
The marketing director wants a VIP campaign: "Find our best customers — the ones who bought recently, buy often and spend the most. How many are there?"
Data
Download the practice file(s):
Steps
- Load orders.csv and order_items.csv, compute line net sales and merge on order_id.
- Per customer compute Recency (days from last order to the snapshot date 2026-01-01), Frequency (distinct orders) and Monetary (total net sales).
- Score each metric 1–5 with pd.qcut on the rank (rank(method='first') avoids duplicate bin edges). For Recency, fewer days = higher score.
- Define Champions as customers with R ≥ 4, F ≥ 4 and M ≥ 4.
- Count them and look at their average spend versus everyone else.
- Export the Champions list to CSV for the campaign team.
Check your answer
How many customers are Champions (R, F and M scores all 4 or 5)?
Show solution
With quintile scores, 188 of the 1,200 customers score 4–5 on all three dimensions. Those are the Champions for the VIP campaign.
import pandas as pd
orders = pd.read_csv('orders.csv', parse_dates=['order_date'])
items = pd.read_csv('order_items.csv')
items['net'] = items['quantity'] * items['unit_price'] * (1 - items['discount'])
df = items.merge(orders, on='order_id')
snapshot = pd.Timestamp('2026-01-01')
rfm = df.groupby('customer_id').agg(
last_order=('order_date', 'max'),
frequency=('order_id', 'nunique'),
monetary=('net', 'sum'))
rfm['recency'] = (snapshot - rfm['last_order']).dt.days
rfm['R'] = pd.qcut(rfm['recency'].rank(method='first'), 5, labels=[5, 4, 3, 2, 1]).astype(int)
rfm['F'] = pd.qcut(rfm['frequency'].rank(method='first'), 5, labels=[1, 2, 3, 4, 5]).astype(int)
rfm['M'] = pd.qcut(rfm['monetary'].rank(method='first'), 5, labels=[1, 2, 3, 4, 5]).astype(int)
champions = rfm[(rfm['R'] >= 4) & (rfm['F'] >= 4) & (rfm['M'] >= 4)]
champions.to_csv('champions.csv')
print(len(champions))Answer: 188 rows