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

  1. Load orders.csv and order_items.csv, compute line net sales and merge on order_id.
  2. Per customer compute Recency (days from last order to the snapshot date 2026-01-01), Frequency (distinct orders) and Monetary (total net sales).
  3. Score each metric 1–5 with pd.qcut on the rank (rank(method='first') avoids duplicate bin edges). For Recency, fewer days = higher score.
  4. Define Champions as customers with R ≥ 4, F ≥ 4 and M ≥ 4.
  5. Count them and look at their average spend versus everyone else.
  6. 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