Data AnalyticsCustomer and product analytics

RFM analysis: validate segments against business actions

PK
Pankit Kumar
Sr. Data Scientist at Parexel (a Goldman Sachs–backed company) · 20 September 2026 · 3 min read
Technically reviewed by Ishaan Sharma
In this article (5 sections)

RFM summarizes how recently a customer purchased, how often they purchased and how much they spent within a specified history. It can organize customer analysis, but a segment name such as “at risk” is an interpretation that needs evidence. A low recency score alone does not establish that a customer is about to leave.

The useful output is a reproducible customer table connected to an appropriate business action, with subsequent evaluation of whether that action helps.

Fix the snapshot and purchase window

Use the original synthetic purchase dataset. The snapshot date is May 1, 2026. Include purchases from January 1 inclusive through May 1 exclusive. Each purchase ID represents one purchase, and amounts are integer paise.

Recency is days since the latest included purchase. Frequency is the number of included purchases. Monetary value is the sum of included amounts. This exercise has no returns or cancellations; a real contract must decide how those affect each measure.

sql
SELECT customer_id,
 CAST(julianday('2026-05-01')-julianday(MAX(purchased_at)) AS INTEGER) AS recency_days,
 COUNT(DISTINCT purchase_id) AS frequency,
 SUM(amount_paise) AS monetary_paise
FROM purchases
WHERE purchased_at>='2026-01-01' AND purchased_at<'2026-05-01'
GROUP BY customer_id ORDER BY customer_id;

Expected results are:

CustomerRecency daysPurchasesMonetary paise
A30335,000
B52325,000
C60220,000
D28240,000
E27115,000

E is the most recent customer but has only one observed purchase. Calling E a loyal customer would require information that this table does not provide.

Verify the aggregation independently

From the product analytics lab directory, this example reads the sibling purchase fixture and checks the full result:

python
import csv
from collections import defaultdict
from datetime import date
from pathlib import Path

groups = defaultdict(list)
with Path('../advanced-sql/purchases.csv').open(newline='', encoding='utf-8') as handle:
    for row in csv.DictReader(handle):
        if '2026-01-01' <= row['purchased_at'] < '2026-05-01':
            groups[row['customer_id']].append(row)
actual = {}
for customer, rows in groups.items():
    latest = max(date.fromisoformat(r['purchased_at']) for r in rows)
    actual[customer] = ((date(2026,5,1)-latest).days,
                        len({r['purchase_id'] for r in rows}),
                        sum(int(r['amount_paise']) for r in rows))
assert actual == {'A':(30,3,35000), 'B':(52,3,25000),
                  'C':(60,2,20000), 'D':(28,2,40000), 'E':(27,1,15000)}
print(actual)

This fixture has unique purchase IDs. Deduplicating frequency while summing replayed amounts would otherwise produce inconsistent measures. Validate the source grain before calculating either.

Choose scores without concealing ties

IBM's RFM analysis documentation describes the three component scores and their combination. A combined label is a convenient summary, not a universal probability of response.

With only five customers and repeated frequencies, five equal-sized frequency bins would create arbitrary distinctions. NTILE can place equal values into different bins depending on ordering. Keep raw measures visible and either use explicit business thresholds or adopt a documented tie policy.

For an illustrative follow-up queue, define “previous repeat purchaser, no purchase for more than 45 days” as frequency at least two and recency above 45. B and C qualify. That rule is transparent, but its usefulness still depends on the product's normal buying cycle.

Validate the proposed action

Before contacting that queue, check eligibility and whether a service issue should be resolved first. Do not automatically discount customers who would return without an incentive.

For a permitted campaign, compare an assigned treatment with a suitable control and evaluate incremental contribution over a fixed horizon. Response rate alone can reward discounts that reduce profit. Freeze the segment before observing the campaign outcome to avoid selecting customers with hindsight.

Also test stability: do customers switch segments because of meaningful behavior or because a quantile boundary moved when new customers arrived? Store the snapshot date, purchase window, threshold version and customer count with every export.

Exercise: extend the history window by a month and add an older purchase for E. Explain why frequency and monetary value change while recency does not. Keep both snapshots reproducible.

NeuraPath's Data Analytics with Generative AI course connects customer-level SQL with business evaluation. An RFM project is stronger when it tests a decision than when it only colors a segmentation chart.

Continue learning

This article is part of the Customer and product analytics sequence. Use the neighbouring tasks when you need the prerequisite or the next application.

PK
Pankit Kumar
Lead Instructor, NeuraPath Academy

Pankit Kumar has 10 years in Data Science & AI, building and shipping production systems in regulated pharma and clinical environments. He is a freelance trainer at Boston Institute of Analytics, AnalytixLabs and Scaler, and has taught this material to thousands of working professionals.

This article is part of our Data Analytics with Generative AI programme — 3–4 months. The full analyst stack — Excel, SQL, Power BI and Python pipelines — then a generative-AI layer you can prove is right.

Explore Data Analytics with Generative AI
Counselling is free · no obligation

Not sure which programme fits?

Tell us your background and we will map it to the right entry point — including saying so when a cheaper programme is the better fit. A counsellor replies within one working day.