<jupyter_start><jupyter_text>RFM for analyzing customer value RFM is a method used for analyzing customer value. "RFM" stands for the three dimensions:1. Recency – How recently did the customer purchase? Customers who have purchased from you recently are more likely to buy from you again than customers who you haven’t seen for a while. 2. Frequency – How often do they purchase? Customers who buy from you more often are more likely to buy again than customers who buy infrequently. 3. Monetary Value – How much do they spend? Customers who spend more are more likely to buy again than customers who spend less.Firstly, we have to decide the number of categories for each RFM attribute. The number and the interval of categories often depends on different business problems. For example, for Recency, it can be 3, 5 or 10 categories with a 2 month intervals. To calculate the value of these three dimension, all we need is the following information:* Customer id* Transaction id* Date* AmountWe then use these information to calculate RFM:1. Recency: the difference between today and the last transaction date for each customer, then decide the interval of it.2. Frequency: how frequently these customers purchase. We can use quantile to make customer into different categories or separate them by some pre-defined rules.3. Monetary Value: total or average sales attributed to the customer.To illustrate how to calculate RFM, we use the data we downloaded from [Online Retail Data Set](http://archive.ics.uci.edu/ml/datasets/Online+Retail) as the sample of this document.  Read Data It's is a transnational data set which contains all the transactions occurring between 01/12/2010 and 09/12/2011 for a UK-based and registered non-store online retail.<jupyter_code>%matplotlib inline
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
color = sns.color_palette()
retail_df = pd.read_excel('_data/Online Retail.xlsx')
retail_df['InvoiceDate_date']=retail_df.InvoiceDate.map(lambda x: x.strftime('%Y-%m-%d'))
retail_df['InvoiceDate_YearMonth']=retail_df.InvoiceDate.map(lambda x: x.strftime('%Y-%m'))
retail_df.head()
retail_df = retail_df[(retail_df.CustomerID.notnull()) & (retail_df.Quantity>0)]
retail_df['CustomerID'] = retail_df['CustomerID'].apply(int).apply(str)<jupyter_output><empty_output><jupyter_text>EDA  Summary Statistics<jupyter_code>retail_df.shape
retail_df.describe()
retail_df.InvoiceDate.describe()<jupyter_output><empty_output><jupyter_text>What are the distribution or count value for each column?<jupyter_code>country_count=sns.countplot(x="Country", data=retail_df, color=color[0],order=retail_df.Country.value_counts().iloc[0:5,].index);
plt.setp(country_count.get_xticklabels(), rotation=45)
sns.despine(bottom=True)<jupyter_output><empty_output><jupyter_text>How many orders are made in each month?<jupyter_code>month_plot=sns.countplot(x="InvoiceDate_YearMonth", data=retail_df, color=color[0]);
plt.setp(month_plot.get_xticklabels(), rotation=45)
sns.despine(bottom=True)<jupyter_output><empty_output><jupyter_text>What are the popular items?<jupyter_code>item_plot=sns.countplot(x="Description", data=retail_df, color=color[0],order=retail_df.Description.value_counts().iloc[0:10,].index);
plt.setp(item_plot.get_xticklabels(), rotation=90);
sns.despine(bottom=True)<jupyter_output><empty_output><jupyter_text>Calculate R Let's define our Recency as 5 if the customer's last order is within 2 month; 4 if it's within 4 months...etc.<jupyter_code>from pandas.tseries.offsets import *
def recency(row):
    last_day=pd.Timestamp(2011, 12, 9)
    if row['InvoiceDate'] > last_day + DateOffset(months=-2):
        val = 5
    elif row['InvoiceDate'] <= last_day + DateOffset(months=-2) and row['InvoiceDate'] > last_day + DateOffset(months=-4):
        val = 4
    elif row['InvoiceDate'] <= last_day + DateOffset(months=-4) and row['InvoiceDate'] > last_day + DateOffset(months=-6):
        val = 3
    elif row['InvoiceDate'] <= last_day + DateOffset(months=-6) and row['InvoiceDate'] > last_day + DateOffset(months=-8):
        val = 2
    else:
        val = 1
    return val
customer_df = pd.DataFrame(retail_df.groupby('CustomerID')['InvoiceDate'].max()).reset_index()
customer_df.head()
customer_df['Recency'] = customer_df.apply(recency, axis=1)
recency_df = pd.DataFrame(retail_df.Recency.value_counts()).reset_index().sort_values(by='index', ascending=False)
recency_df
recency_plot=sns.countplot(x="Recency", data=retail_df, color=color[0]);
# plt.setp(item_plot.get_xticklabels(), rotation=90);
sns.despine(bottom=True)
final_customer_df = customer_df[['CustomerID','Recency']]
final_customer_df.head()<jupyter_output><empty_output><jupyter_text>Calculate F Let's use the distribution of the frequency of all the customers and take its quantile as our frenquency score. For simplicity, I define the Frequency here as "The total number of the order for each user within last 365 days" instead of "How often do they purchase in certain period of time". Because of the distribution of our frequency, we make our F into 8 levels.<jupyter_code>target_date = str(pd.Timestamp(retail_df.InvoiceDate_date.max())+ DateOffset(months=-12))

frequency_df = pd.DataFrame(retail_df[retail_df.InvoiceDate_date > target_date].groupby('CustomerID')['InvoiceNo'].nunique()
).reset_index()
frequency_df = frequency_df.rename(columns={'InvoiceNo':'Count'})
frequency_df.head()
frequency_df['Freqency'] = pd.qcut(frequency_df['Count'], 20, labels=[1,2,3,4,5,6,7,8],duplicates='drop')
frequency_df.head()
frequency_plot=sns.countplot(x="Freqency", data=frequency_df, color=color[0]);
plt.setp(frequency_plot.get_xticklabels(), rotation=15);
sns.despine(bottom=True)
final_customer_df = pd.merge(final_customer_df,frequency_df[['CustomerID','Freqency']],on='CustomerID', how='left')
final_customer_df.head()<jupyter_output><empty_output><jupyter_text>Calculate M For the monetary value, let's use the distribution of the total purchase within 1 year of all the customers and take its quantile as our monetary score score.<jupyter_code>retail_df['total_price']=retail_df['Quantity'] * retail_df['UnitPrice']
target_date = str(pd.Timestamp(retail_df.InvoiceDate_date.max())+ DateOffset(months=-12))

monetary_df = pd.DataFrame(retail_df[retail_df.InvoiceDate_date > target_date].groupby('CustomerID')['total_price'].agg('sum')
).reset_index()
monetary_df.head()
monetary_df['Monetary'] = pd.qcut(monetary_df['total_price'], 5, labels=[1,2,3,4,5])
monetary_plot=sns.countplot(x="Monetary", data=monetary_df, color=color[0]);
plt.setp(monetary_plot.get_xticklabels(), rotation=15);
sns.despine(bottom=True)
final_customer_df = pd.merge(final_customer_df,monetary_df[['CustomerID','Monetary']],on='CustomerID', how='left')<jupyter_output><empty_output><jupyter_text>Get the Final RFM Score<jupyter_code>final_customer_df.head()
final_customer_df['Recency'] = final_customer_df['Recency'].apply(int).apply(str)
final_customer_df['Freqency'] = final_customer_df['Freqency'].apply(int).apply(str)
final_customer_df['Monetary'] = final_customer_df['Monetary'].apply(int).apply(str)
final_customer_df['RFM'] = final_customer_df[['Recency','Freqency','Monetary']].apply(lambda x : '{}{}{}'.format(x[0],x[1],x[2]), axis=1)
final_customer_df.head()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12363088718510405, 'fraction_numerical': 0.014238773274917854, 'mean_word_length': 7.454861111111111, 'pattern_counts': {'":': 0, '<': 40, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '261568', 'license': 'MIT', 'n_tokens_mistral': 2463, 'n_tokens_neox': 2353, 'n_words': 588, 'path': 'CustomerLifetimeValue/RFM/RFM.ipynb', 'repo_name': 'johnnychiuchiu/Machine-Learning', 'size': '7304'}