Customer Segmentation Using RFM Analysis: Overview
Customer Segmentation Using RFM Analysis: Overview
Overview:
In this blog, we will be exploring some concepts and analyses around RFM. we will be covering what is
RFM and how we can use these factors to segment the customers and target our marketing campaigns
based on these RFM values
Introduction:
What is RFM?
RFM is a method used to analyze customer value. RFM stands for RECENCY, Frequency, and Monetary.
RECENCY: How recently did the customer visit our website or how recently did a customer purchase?
Monetary: How much revenue we get from their visit or how much do they spend when they purchase?
For example, if we see the sales data in the last 12 months, the RFM will look something like below
Why is it needed?
RFM Analysis is a marketing framework that is used to understand and analyze customer behaviour based
on the above three factors RECENCY, Frequency, and Monetary.
The RFM Analysis will help the businesses to segment their customer base into different homogenous
groups so that they can engage with each group with different targeted marketing strategies.
RFM on Adventure works database:
Now, let’s start the real part. For this, I chose the Adventure works database that is available publicly
Adventure Works Cycles a multinational manufacturing company. The company manufactures and sells
metal and composite bicycles to North American, European, and Asian commercial markets.
The database contains many details. But, I am just concentrating on the Sales details to get RFM values
and segment the customers based on RFM values.
We have to identify the dimension tables and fact tables from the database based on our requirements.
I have prepared 5NF Star Schema (Fact, Customer, Product, Date, Location) from the database imported
From the above tables, we can write an SQL query to Join all the tables and get the necessary data.
[YearlyIncome] > 60000 THEN 'High' ELSE 'Moderate' END ,d.[CalendarYear] ,f.[OrderDate] ,f.[SalesOrderNumber]
,f.SalesOrderLineNumber ,f.OrderQuantity ,f.ExtendedAmount FROM [dbo].[FactInternetSales] f, [dbo].[DimDate]
d, [dbo].[DimProduct] p, [dbo].[DimProductSubcategory] psc, [dbo].[DimProductCategory] pc, [dbo].
[DimCustomer] c, [dbo].[DimGeography] g, [dbo].[DimSalesTerritory] s where f.[OrderDateKey] = d.[DateKey] and
f.[ProductKey] = p.[ProductKey] and p.[ProductSubcategoryKey] = psc.[ProductSubcategoryKey] and psc.
From the sales data we have, we calculate RFM values in Python and Analyze the customer behaviour and
segment the customers based on RFM values.
aw_df.isnull().sum()
Once you are good with the data, we are good to start doing Exploratory Data Analysis aka. EDA
Now, let’s check how much are sales happened for each product category and how many quantities each
category is being sold.
product_df = aw_df[['EnglishProductCategoryName','Amount']]
product_df1 = aw_df[['EnglishProductCategoryName','Quantity']]
product_df.groupby("EnglishProductCategoryName").sum().plot(kind="bar",ax=axarr[0])
product_df1.groupby("EnglishProductCategoryName").sum().plot(kind="bar",ax=axarr[1])
We can see, Bikes account for huge revenue generation even though accessories are being sold in high
quantity. This might be because the cost of Bikes will be higher than the cost of Accessories.
['CustomerKey'].nunique().sort_values(ascending=False).reset_index().head(11)
sns.barplot(data=Customer_Country,x='Country',y='CustomerKey',palette='Blues',orient=True,ax=axarr[0])
Customer_Region = aw_df1.groupby('Region')
['CustomerKey'].nunique().sort_values(ascending=False).reset_index().head(11)
sns.barplot(data=Customer_Region,x='Region',y='CustomerKey',palette='Blues',orient=True,ax=axarr[1])
Recency
df_recency.columns = ['CustomerKey','max_date']
The difference between the reference date and maximum date in the dataframe for each customer(which is
the recent visit) is Recency
df_recency['Recency'] = df_recency['max_date'].apply(lambda row: (reference_date - row).days)
df_recency.drop('max_date',inplace=True,axis=1) df_recency[['CustomerKey','Recency']].head()
CustomerKey Recency
0 11000 212
1 11001 319
2 11002 281
3 11003 205
Recency plot
plt.figure(figsize=(8,5))
sns.distplot(df_recency.Recency,bins=8,kde=False,rug=True)
We can see the customers who come within last 2 months are more and there are some customers that
didn’t order more than a year. This way we can identify the customer and target them differently. But it is too
early to say with only Recency value.
Frequency:
We can get the Frequency of the customer by summing up the number of orders.
CustomerKeyFrequency
11000 5
11001 6
11002 2
11003 4
11004 3
Frequency plot
plt.figure(figsize=(8,5)) sns.distplot(df_frequency,bins=8,kde=False,rug=True)
We can see the customers who order 2 times are more and then we see who orders 3 times. But there is very
less number of customers that orders more than 5 times.
Monetary:
Now, it’s time for our last value which is Monetary.
Monetary can be calculated as the sum of the Amount of all orders by each customer.
Customer
Monetary
Key
0 11000 4849
1 11001 2419.93
2 11002 2419.06
3 11003 4739.3
4 11004 4796.02
Monetary Plot
plt.figure(figsize=(8,5)) sns.distplot(df_monetary.Monetary,kde=False,rug=True)
We can clearly see, the customers spend is mostly less than 200$. This might be because they are buying
more accessories. This is common since we buy Bikes once or twice a year but we buy accessories more.
We cannot come to any conclusion based on taking only Recency or Frequency or Monetary values
independently. we have to take all 3 factors.
Let’s merge the Recency, Frequency, and Monetary values and create a new dataframe
r_f_m = r_f.merge(df_monetary,on='CustomerKey')
CustomerKeyRecencyLineNumberMonetary
Scatter Plot:
When we have more than two variables, we choose a scatter plot to analyze.
Recency Vs frequency
plt.scatter(r_f_m.groupby('CustomerKey')['Recency'].sum(), aw_df1.groupby('CustomerKey')['Quantity'].sum(),
color = 'red', marker = '*', alpha = 0.3) plt.title('Scatter Plot for Recency and Frequency')
plt.xlabel('Recency') plt.ylabel('Frequency')
We can see the customers whose Recency is less than a month have high Frequency i.e the customers
buying more when their recency is less.
Frequency Vs Monetary
market_data['Quantity'], color = 'red', marker = '*', alpha = 0.3) plt.title('Scatter Plot for Monetary and
Frequency') plt.xlabel('Monetary') plt.ylabel('Frequency')
We can see, customers buying frequently are spending less amount. This might be because we frequently
buy Accessories which are less costly.
Now, in the above plot, the color specifies Monetary. From the above plot, we can say the customers whose
Recency is less have high Frequency but less Monetary.
This might vary from case to case and company to company. That is why we need to take all the 3 factors
into consideration to identify customer behavior.
How do we Segment:
We can bucket the customers based on the above 3 Factors(RFM). like, put all the customers whose
Recency is less than 60 days in 1 bucket. Similarly, customers whose Recency is greater than 60 days and
less than 120 days in another bucket. we will apply the same concept for Frequency and Monetary also.
Depending on the Company’s objectives, Customers can be segmented in several ways. so that it is
financially possible to make marketing campaigns.
The ideal customers for e-commerce companies are generally the most recent ones compared to the date
of study(our reference date) who are very frequent and who spend enough.
Based on the RFM Values, I have assigned a score to each customer between 1 and 3(bucketing them). 3 is
the best score and 1 is the worst score.
Ex: A Customer who bought most recently and most often, and spent the most, his RFM score is 3–3–3
Bucketing Recency:
def R_Score(x): if x['Recency'] 60 and x['Recency'] <=120: recency = 2 else: recency = 1 return recency
r_f_m['R'] = r_f_m.apply(R_Score,axis=1)
Bucketing Frequency
def F_Score(x): if x['LineNumber'] 3 and x['LineNumber'] <=6: recency = 2 else: recency = 1 return recency
r_f_m['F'] = r_f_m.apply(F_Score,axis=1)
Bucketing Monetary
M_Score = pd.qcut(r_f_m['Monetary'],q=3,labels=range(1,4))
r_f_m = r_f_m.assign(M = M_Score.values)
CustomerKeyRecency LineNumberMonetary R F M
R-F-M Score
Now, let’s find the R-F-M Score for each customer by combining each factor.
If the R-F-M score of any customer is 3-3-3. His Recency is good, frequency is more and Monetary is more.
So, he is a Big spender.
Similarly, if his score is 2-3-3, then his Recency is better and frequency and monetary are good. This
customer hasn’t purchased for some time but he buys frequently and spends more.
we can have something like the below for all different segments
Now, we just have to do this in python. don’t worry, we can do it pretty easily as below.
r_f_m['segment'] = segment
Big
0 11000 212 5 4849 1 2 3 123
Spenders
Big
1 11001 319 6 2419.93 1 2 3 123
Spenders
Lost
2 11002 281 2 2419.06 1 3 3 133
Customers
Big
3 11003 205 4 4739.3 1 2 3 123
Spenders
Lost
4 11004 214 3 4796.02 1 3 3 133
Customers
Big
5 11005 213 4 4746.34 1 2 3 123
Spenders
Now, lest plot a bar plot to identify the customer base for each segment.
Recommendations:
Best Customers: We can Reward them for their multiples purchases. They can be early adopters to very
new products. Suggest them “Refer a friend”. Also, they can be the most loyal customers that have the
habit to order.
Loyal Customers: Create loyalty cards in which they can gain points each time of purchasing and these
points could transfer into a discount
This is how we can target a customer based on the customer segmentation which will help in marketing
campaigns. Thus saving marketing costs, grab the customer, make customers spend more thereby
increasing the revenue.
The media shown in this ar ticle are not owned by Analytics Vidhya and are used at the Author’s
discretion.