Usage Of CRM Analysis To Become A Competitive Superstar
By: Heliya Hasani
Tags: Data, Rfm, Cltv, CRM

In this article, I will try to explain two basic analysis of CRM which are RFM and CLTV. Furhermore, I will give an example to illustrate the importance of customer data which will be the guide line for taking actions for a business.

What is CRM ?

Customer relationship management (CRM) is a tool that allows us to see the relationship between our customers and our company. According to the author the four core objectives of CRM’s are;

Boost Customer Satisfaction Improve The Efficiency Of Your Business Gain New Customers Strengthen Your Sales And Support Teams

(Micheal,2014,p.1)

RFM And CLTV

As I mentioned before, today we will discuss two CRM analysis concept which are RFM(Recency — Frequency — Monetary) and CLTV(Customer Life Time Value).

RFM

RFM is an analysis that allows us to segment our customers into specific segments based on their behavior.

Recency: Time since last purchase.

Frequency: Total repeat purchases.

Monetary: Average earnings per purchase.

RFM Analysis Chart

According to table above we can clearly say that :

[1–2][1–2]: ‘hibernating’,

[1–2][3–4]: ‘at_risk’,

[1–2]5: ‘cant_loose’,

[1–2]: ‘about_to_sleep’,

[3-3]: ‘need_attention’,

[3–4][4–5]: ‘loyal_customers’,

[4-1]: ‘promising’,

[5-1]: ‘new_customers’,

[4–5][2–3]: ‘potential_loyalists’,

5[4–5]: ‘champions

CLTV

According to authors, the average revenue you can produce from customers over the course of their account’s lifetime is known as Customer Lifetime Value (CLV or CLTV) so that, it’s the money you’d make from a customer before they churned. (NUPURA UGHADE &BHARGAVI P,2021,p.2)

Example Project

Business Problem

An e-commerce site wants a forward-looking projection for customer actions according to the CLTV values of its customers.With the dataset in your hand, is it possible to identify the customers who can generate the most revenue within 6-month time period?

Dataset Story

The dataset named Online Retail II includes the sales of a UK-based online store between 01/12/2009–09/12/2011.

The product catalog of this company includes souvenirs. They can also be considered as promotional items.

Dataset

online_retail_II_xlsx

Variables

InvoiceNo — Invoice Number If this code starts with C, it means that the transaction has been cancelled.

— Invoice Number If this code starts with C, it means that the transaction has been cancelled. StockCode — Product code Unique number for each product.

— Product code Unique number for each product. Description — Product name

— Product name Quantity — Number of products Indicates how many of the products on the invoices have been sold.

— Number of products Indicates how many of the products on the invoices have been sold. InvoiceDate — Invoice date

— Invoice date UnitPrice — Invoice price (Sterling)

— Invoice price (Sterling) CustomerID — Unique customer number

— Unique customer number Country — Country name

(Reference — VBO)

Let’s start Coding!

Import our libraries to clean our data. Import the dataset. See first 5 rows of the data that we upload to identify the set. See descriptive statistics of quantitative datas.

import datetime as dt

import pandas as pd

pd.set_option('display.max_columns', None)

pd.set_option('display.max_rows', None)

pd.set_option('display.float_format', lambda x: '%.5f' % x)# 2009-2010 year dataset

df_ = pd.read_excel(".../online_retail_II.xlsx", sheet_name="Year 2009-2010")df = df_.copy()

df.head()

statistics of the dataset; df.describe().T

Data Preperation:

5. Are there any missing observations in the dataset? If yes, how many missing observations in each variable?

df.isnull().sum()

6. As it seen, there are missing values. Let’s drop them.

df.dropna(inplace=True)

7. Total quantities of products

df['Description'].value_counts().head(10)

8. Sorting the most ordered products from most to least

df.groupby('Description').agg({'Quantity':'sum'}).sort_values('Quantity', ascending=False

9. ‘C’ in invoices indicates canceled transactions. Let’s remove the canceled transactions from the dataset.

df = df[~df['Invoice'].apply(str).str.contains('C', na=False)]

10. Let’s create a variable called ‘TotalPrice’ that represents the total earnings per invoice.

df["TotalPrice"] = df["Quantity"] * df["Price"]

Calculating RFM metrics:

11.

df["InvoiceDate"].max()

today_date = dt.datetime(2011, 12, 11)rfm = df.groupby('Customer ID').agg({'InvoiceDate': lambda date: (today_date - date.max()).days,

'Invoice': lambda num: num.nunique(),

'TotalPrice': lambda TotalPrice: TotalPrice.sum()})rfm.columns = ['recency', 'frequency', 'monetary']rfm.head()

12. After creating the RFM dataframe, filter the dataset to “monetary>0” because if there negative values are corrupted;

rfm = rfm[rfm["monetary"] > 0]

rfm

Calculating RFM Scores:

13. Converting Recency, Frequency and Monetary metrics to scores between 1–5 with the help of qcut and recording these scores as recency_score, frequency_score and monetary_score. It expresses the value of 2 different variables as a single variable and saves it as RFM_SCORE.

rfm["recency_score"] = pd.qcut(rfm['recency'], 5, labels=[5, 4, 3, 2, 1])rfm["frequency_score"] = pd.qcut(rfm['frequency'].rank(method="first"), 5, labels=[1, 2, 3, 4, 5])# 1 1,1,2,3,3,3,3,3,rfm["monetary_score"] = pd.qcut(rfm['monetary'], 5, labels=[1, 2, 3, 4, 5])rfm["RFM_SCORE"] = (rfm['recency_score'].astype(str) +

rfm['frequency_score'].astype(str))rfm.head()

Defining RFM scores as segments:

14.Define segments so that the generated RFM scores.

seg_map = {

r'[1-2][1-2]': 'hibernating',

r'[1-2][3-4]': 'at_Risk',

r'[1-2]5': 'cant_loose',

r'3[1-2]': 'about_to_sleep',

r'33': 'need_attention',

r'[3-4][4-5]': 'loyal_customers',

r'41': 'promising',

r'51': 'new_customers',

r'[4-5][2-3]': 'potential_loyalists',

r'5[4-5]': 'champions'

}rfm['segment'] = rfm['RFM_SCORE'].replace(seg_map, regex=True)rfm.head()

Comments and Actions Due to RFM:

Let’s choose 3 segments that we find important. These three segments;

rfm[["segment", "recency", "frequency", "monetary"]].groupby("segment").agg(["mean", "count","max"])

Champions

About to Sleep

Can’t Loose

Champions

There are 633 people in this group.

They do not shop for an average of 6.36 days.

They shopped an average of 12.41 times.

They earned an average of 6857.96 units of money.

Action Decision That Can Be Taken for Champions: The best customers are the last, the most frequent purchasers and the ones who contribute the most to the company because finding a new customer is always the hardest. We can categorize them as a premium customer and give prime offers such as free shipping.

About to Sleep

There are 352 people in this segment,

They do not shop for an average of 53.31 days.

They shopped an average of 1.16 times.

They earned an average of 471.99 units of money.

Action Decision That Can Be Taken for About to Sleep: We can give them discount checks which will encourage them to purchase from our company.

Can’t Loose

There are 63 people in this segment,

They do not shop for an average of 132.96 days.

They shopped an average of 8.38 times.

They earned an average of 2796.1558 units of money.

Action Decision That Can Be Taken for Can’t Loose: It is one of the segments that should be given importance. These people categorized as can’t lose might become a champions. We can send notifacations about privilege of premium customers and why they should become one of them.

Calculating CLTV:

15. Let’s assume we would like to target UK customers and learn their life cycles in our company.

16. Again we define RFM metrics but we add a T value to calculate customer’s age which means:

T: Customer age = Analysis date — Customer’s first purchase date.

df = df[df["Country"] == 'United Kingdom']

df["TotalPrice"] = df["Quantity"] * df["Price"]



today_date = dt.datetime(2011, 12, 11)





cltv_df = df.groupby('Customer ID').agg({'InvoiceDate': [lambda date: (date.max() - date.min()).days,

lambda date: (today_date - date.min()).days],

'Invoice': lambda num: num.nunique(),

'TotalPrice': lambda TotalPrice: TotalPrice.sum()})



cltv_df.columns = cltv_df.columns.droplevel(0)

cltv_df.columns = ['recency', 'T', 'frequency', 'monetary']





cltv_df["monetary"] = cltv_df["monetary"] / cltv_df["frequency"]



cltv_df = cltv_df[(cltv_df['frequency'] > 1)]



cltv_df = cltv_df[cltv_df["monetary"] > 0]



cltv_df["recency"] = cltv_df["recency"] / 7



cltv_df["T"] = cltv_df["T"] / 7



cltv_df["frequency"] = cltv_df["frequency"].astype(int)

17. Building our models to predict expected average profit.

#BG-NBD



bgf = BetaGeoFitter(penalizer_coef=0.001)



bgf.fit(cltv_df['frequency'],

cltv_df['recency'],

cltv_df['T'])





#GAMMA-GAMMA



ggf = GammaGammaFitter(penalizer_coef=0.01)

ggf.fit(cltv_df['frequency'], cltv_df['monetary'])





ggf.conditional_expected_average_profit(cltv_df['frequency'],

cltv_df['monetary']).head(10)





ggf.conditional_expected_average_profit(cltv_df['frequency'],

cltv_df['monetary']).sort_values(ascending=False).head(10)



cltv_df["expected_average_profit"] = ggf.conditional_expected_average_profit(cltv_df['frequency'],

cltv_df['monetary'])

18. The business problem was predicting 6 months expexted profits. We build our model due to that and sort values highest to lowest.

cltv = ggf.customer_lifetime_value(bgf,

cltv_df['frequency'],

cltv_df['recency'],

cltv_df['T'],

cltv_df['monetary'],

time=6, # 6 months

freq="W", # T's frequency.

discount_rate=0.01)



cltv.head()





cltv = cltv.reset_index()

cltv.sort_values(by="clv", ascending=False).head(5)



cltv_final = cltv_df.merge(cltv, on="Customer ID", how="left")



cltv_final.sort_values(by="clv", ascending=False).head(10)

Solution: Higher clv is better because it means greater profit can be earn in that time period. For instance above table illustrates that customer id 16446 has the highest clt which will bring higher profit. Customer Id 16446’s monatery value is 84236,25 and expected average profit in 6 months is 92172,26991. On the other hand the frequency is low but this customer makes big purchases from that company.

Like above we can make comments and build marketing strategies due to data on hand !

“ CRM isn’t rocket science but it can make you a competitive superstar.

-Unknown. “

References