Not all customers are equal. Some buy frequently, spend generously, and purchased just last week. Others placed a single order two years ago and never came back. RFM analysis scores every customer on three dimensions: how recently they bought (Recency), how often they buy (Frequency), and how much they spend (Monetary value), then places each customer in a named segment using their recency and frequency scores, such as Champions, Loyal, At Risk, and Hibernating. Spend is scored too, but it does not decide the segment. Upload transaction data to view customer segments, charts, and suggested actions.
Worked Example (Simulated): Ten Customers Scored and Segmented
Question: Which customers in a small sample have recent repeat buys, and how much of the sample's sales came from them?
Inputs: Simulated order rows for ten customers, seed 42. Each order has an order ID, an age in days typed into the script by hand, and a sale amount drawn with a fixed seed. These are not real customers. The script uses only the Python standard library.
Method: Rank each measure into five equal groups of two customers. A lower day count gets a higher recency score. The script places each customer in one named segment using the recency and frequency scores only. Sales is scored but does not set a segment. Ties use customer ID, so two customers with the same order count can land in different groups: C01 and C09 both have three orders, with frequency scores 3 and 5.
import random
from collections import defaultdict
SEED = 42
orders_ages = {
"C01": [5, 20, 40],
"C02": [10, 30, 70],
"C03": [15, 65, 100],
"C04": [120, 200],
"C05": [200],
"C06": [2],
"C07": [80, 100],
"C08": [30, 90, 150, 250],
"C09": [55, 90, 160],
"C10": [70],
}
rng = random.Random(SEED)
transactions = []
for customer, ages in orders_ages.items():
for order_num, age in enumerate(ages, start=1):
transactions.append({
"customer": customer, "invoice": f"{customer}-{order_num}",
"days_ago": age, "revenue": rng.randint(10, 100)})
by_customer = defaultdict(list)
for row in transactions:
by_customer[row["customer"]].append(row)
cust = {}
for c, rows in by_customer.items():
cust[c] = {"id": c,
"recency": min(r["days_ago"] for r in rows),
"frequency": len({r["invoice"] for r in rows}),
"monetary": sum(r["revenue"] for r in rows)}
# Split each ranked measure into five equal groups of two. Ties: customer ID.
def score(field, reverse=False):
ordered = sorted(cust.values(), key=lambda c: (c[field], c["id"]),
reverse=reverse)
return {c["id"]: 5 - rank // 2 for rank, c in enumerate(ordered)}
r_score = score("recency")
f_score = score("frequency", reverse=True)
m_score = score("monetary", reverse=True)
def segment(r, f):
if r >= 4 and f >= 4: return "Champions"
if r == 3 and f >= 4: return "Loyal"
if r >= 4 and f in (2, 3): return "Potential Loyalist"
if r >= 4 and f == 1: return "New Customers"
if r == 1 and f >= 4: return "Can't Lose Them"
if (r == 1 and f == 3) or (r == 2 and f >= 3): return "At Risk"
if r <= 2 and f <= 2: return "Hibernating"
return "Need Attention"
for c in cust.values():
c["rfm"] = (r_score[c["id"]], f_score[c["id"]], m_score[c["id"]])
c["segment"] = segment(c["rfm"][0], c["rfm"][1])
total = sum(c["monetary"] for c in cust.values())
print(f"Simulated data, seed {SEED}")
print(f"Transactions: {len(transactions)}; customers: {len(cust)}; "
f"total sales: {total}")
print("Scoring: five rank groups of two; "
"recency scores higher when days are lower")
print("Segments: recency and frequency scores only; "
"sales is scored but does not set a segment")
print("Customer Recency_days Frequency Sales RFM Segment")
for c in sorted(cust.values(), key=lambda c: c["id"]):
r, f, m = c["rfm"]
print(f"{c['id']:8} {c['recency']:12} {c['frequency']:9} "
f"{c['monetary']:5} {r}{f}{m} {c['segment']}")
print("Segment Customers Sales Share_of_sales_pct")
for name in ("Champions", "Loyal", "Potential Loyalist", "New Customers",
"Can't Lose Them", "At Risk", "Hibernating", "Need Attention"):
g = [c for c in cust.values() if c["segment"] == name]
s = sum(c["monetary"] for c in g)
print(f"{name:19} {len(g):9} {s:5} {100 * s / total:17.1f}")
Printed output:
Simulated data, seed 42
Transactions: 23; customers: 10; total sales: 1061
Scoring: five rank groups of two; recency scores higher when days are lower
Segments: recency and frequency scores only; sales is scored but does not set a segment
Customer Recency_days Frequency Sales RFM Segment
C01 5 3 128 534 Potential Loyalist
C02 10 3 124 443 Champions
C03 15 3 146 444 Champions
C04 120 2 100 123 Hibernating
C05 200 1 85 112 Hibernating
C06 2 1 64 512 New Customers
C07 80 2 27 231 At Risk
C08 30 4 171 355 Loyal
C09 55 3 181 355 Loyal
C10 70 1 35 221 Hibernating
Segment Customers Sales Share_of_sales_pct
Champions 2 270 25.4
Loyal 2 352 33.2
Potential Loyalist 1 128 12.1
New Customers 1 64 6.0
Can't Lose Them 0 0 0.0
At Risk 1 27 2.5
Hibernating 3 220 20.7
Need Attention 0 0 0.0
Result: Champions are 2 of 10 customers and 25.4% of sample sales. Loyal has 2 customers and 33.2%. Hibernating has 3 and 20.7%. These shares describe this made-up sample only.
Limit: The group rules follow the standard RFM tool and use recency and frequency only. The order ages were chosen by hand, so the counts per group are built in, not found. This small simulated set cannot show how well the groups guide a campaign.
What Is RFM Analysis?
RFM groups customers by when they last bought, how often they bought, and how much they spent. It evaluates every customer on three behavioral dimensions. Recency measures how many days since their last purchase: a customer who bought yesterday is more likely to buy again than one who last bought six months ago. Frequency counts how many separate transactions they have made: repeat buyers are more valuable and more responsive to marketing than one-time purchasers. Monetary value sums their total spending: high spenders deserve different treatment than bargain hunters.
To see which of your own customers are most valuable and which are slipping away, try the free RFM segmentation tool.
Each customer gets a score on each part of RFM. A score of 555 is high on all three parts; 111 is low on all three. The scores are then mapped to named segments that marketing teams can act on: Champions (recent, frequent buyers: reward and retain them), Loyal (frequent buyers who may not be the biggest spenders: upsell opportunities), At Risk (previously good customers whose recency is declining: send win-back campaigns), and Hibernating (have not bought in a long time: last-chance reactivation). The segment is set by the recency and frequency scores. Spend is scored too, but it does not decide the segment.
The power of RFM is its simplicity and directness. You do not need a data science team, machine learning models, or complex feature engineering. You need transaction data (who bought what, when, and for how much) and the RFM framework turns that into a customer segmentation that directly maps to marketing actions.
When to Use RFM Analysis
Quarterly customer reviews are the natural cadence. Every quarter, export your transaction data and run RFM to see how your customer segments have shifted. Are more customers becoming Champions, or are they sliding into At Risk? Is your Loyal segment growing? These trend questions guide strategic decisions about retention investment, acquisition targeting, and marketing budget allocation.
Email campaign planning is the most immediate tactical use case. Before sending a promotional email, segment your customer list using RFM and tailor the message. Champions get exclusive early access or loyalty rewards. At Risk customers get win-back offers with urgency. New customers get onboarding content. Hibernating customers get a final "we miss you" offer with a steep discount. You can test an RFM-based email plan against a broad email send, then compare the results for your own customers.
Budget allocation between acquisition and retention is another high-value use case. If your RFM analysis shows that 60% of revenue comes from Champions and Loyal customers (the top two segments), then retention spending has outsized ROI. If most of your revenue comes from New customers making single purchases, you have a retention problem and need to invest in loyalty programs before spending more on acquisition.
Product and pricing strategy also benefits. A product view of the segments can show which products your Champions buy versus your At Risk customers. If Champions gravitate toward premium products while At Risk customers bought only discounted items, you know your discount strategy might be attracting low-value customers who never return.
What Data Do You Need?
You need a CSV with transaction-level data: one row per line item or per order. The four required columns are: customer_id (a unique identifier for each customer), invoice_date (the date of the transaction), invoice (the order or invoice number), and revenue (the monetary value of the transaction. This can be the line item total or order total). Extra columns, such as country or product, are not needed for the segments above.
Most e-commerce platforms let you export this data directly. In Shopify, export Orders as CSV. You get customer email (as customer_id), created_at (as invoice_date), order name (as invoice), and total (as revenue). In WooCommerce, use the built-in order export. For custom platforms, any transaction log with customer, date, order ID, and amount will work.
The module supports several parameters. min_transactions (default 1) filters out customers with fewer than N transactions: set to 2 to exclude one-time buyers from the segmentation if you only want to analyze repeat customers. scoring_method (default "quintile") determines how RFM scores are assigned: quintile scoring divides customers into five equal-sized groups per dimension, which works well for most datasets. segment_labels (default true) maps RFM score combinations to named segments like Champions, Loyal, At Risk, etc.
How to Read the Report
The worked example above shows how transaction rows can be grouped by recency, frequency, and total spend.
Segment Profile. A table showing each RFM segment with its customer count, percentage of total customers, average recency, average frequency, average monetary value, and total revenue contribution. This is where you see the composition of your customer base at a glance. In the simulated example above, 2 of 10 customers are Champions and their sales are 25.4% of the sample total.
Segment Treemap. A visual representation of segment sizes, with rectangle areas proportional to customer count or revenue. The treemap makes the relative importance of each segment immediately intuitive. You can see at a glance that Champions dominate revenue even if they are a small share of customers.
RF Heatmap. A two-dimensional heatmap with Recency score on one axis and Frequency score on the other, colored by customer count or average monetary value. This reveals the joint distribution of recency and frequency, where customers cluster and where the gaps are. A concentration in the high-recency, low-frequency corner means you have many new one-time buyers who have not returned yet.
Customer Scatter. Individual customers plotted on a recency-vs-monetary or frequency-vs-monetary chart, colored by segment. Outliers stand out: a single customer who spent 50x the median might warrant personal account management. Clusters of At Risk customers in the high-monetary zone represent your biggest retention opportunities.
Revenue Concentration. A Pareto analysis showing what percentage of customers generate what percentage of revenue. Use the revenue view to check how sales are split across customers in your own data. This quantifies how dependent your business is on a small number of high-value customers.
RFM Distributions. Histograms showing the distribution of Recency, Frequency, and Monetary values across your customer base. These reveal the shape of your customer behavior: is recency heavily skewed (most customers bought recently), or spread out (customers buy sporadically)?
Order Distribution. Histogram of order counts per customer. How many customers placed 1 order, 2 orders, 3 orders, etc.? This shows your repeat purchase rate and how steeply it drops off.
Marketing Actions. Specific, actionable recommendations mapped to each segment. Champions: send loyalty rewards, ask for referrals, offer VIP access. At Risk: send win-back email sequence with personalized product recommendations. Hibernating: final reactivation offer with aggressive discount.
Cohort Retention. Customers grouped by their first purchase month, with retention rates tracked over subsequent months. This shows whether your recent acquisition cohorts are retaining better or worse than older cohorts, a leading indicator of business health.
TL;DR. AI-generated executive summary with segment distribution, top retention risks, biggest opportunities, and recommended priority actions.
When to Use Something Else
If you want to predict which customers will churn using machine learning rather than rule-based segmentation, consider the XGBoost or Random Forest classification modules with engineered RFM features as inputs. RFM segments are descriptive. They tell you who is at risk right now. Predictive models tell you who will be at risk next month.
If you want to estimate the future lifetime value of each customer (not just their historical spend), use the Customer Lifetime Value (BG/NBD) module. It uses probabilistic modeling to project how much each customer will spend over their remaining lifetime, which is more sophisticated than the backward-looking Monetary component of RFM.
If your data is at the customer level rather than transaction level (one row per customer with pre-aggregated metrics), you might prefer the Customer Segmentation RFM module, which works with pre-computed recency, frequency, and monetary columns rather than raw transaction data.
The R Code Behind the Analysis
Every report names its method and includes the R code that produced it, so you can reproduce, audit and cite it. The method code is fixed, not rewritten for each run, so the same data gives the same analysis every time.
The analysis uses dplyr for transaction aggregation: grouping by customer_id, computing recency (days since last purchase), frequency (distinct invoice count), and monetary (total revenue). Quintile scoring uses ntile() from dplyr, with recency inverted (lower days = higher score). Segment labels are mapped from RFM score combinations using a lookup table based on the standard RFM segmentation framework. All code is visible in the report's code tab.
Your turn
Bring your own data and the question you actually need answered.
MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai