ysaz (ImanazaS) blog

最近はデータ分析や機械学習が中心。たまに音楽や書評。

Pythonを使ったRFM分析

今回はこれまでと趣向を変えて、サンプルデータを使った分析手法(RFM分析)について取り上げる。

RFM分析は、Recency(直近)、Frequency(頻度)、Monetary(購入額)の略であり、マーケティングの分野において、顧客をグループ化した上で優良顧客を抽出し、確度の高い施策を講じる際に用いられる。

今回サンプルデータとして、以下にアップされているものを利用した。
RFM-analysis/sample-orders.csv at master · joaolcorreia/RFM-analysis · GitHub

import pandas as pd
import matplotlib.pyplot
import datetime as dt

# ファイルの読み込み
df = pd.read_csv('sample-orders.csv',sep=',')
df['order_date'] = pd.to_datetime(df['order_date'])
df.head()

#   order_date        order_id          customer  grand_total
# 0 2011-09-07  CA-2011-100006       Dennis Kane          378
# 1 2011-07-08  CA-2011-100090        Ed Braxton          699
# 2 2011-03-14  CA-2011-100293  Neil Franz�sisch           91
# 3 2011-01-29  CA-2011-100328   Jasper Cacioppo            4
# 4 2011-04-08  CA-2011-100363       Jim Mitchum           21

NOW = dt.datetime(2014,12,31)

# 顧客名を軸にデータをグループ化し、R、F、Mの3つの列を作成
rfmTable = df.groupby('customer').agg({'order_date': lambda x: (NOW - x.max()).days, # Recency
                                        'order_id': lambda x: len(x),      # Frequency
                                        'grand_total': lambda x: x.sum()}) # Monetary Value

rfmTable['order_date'] = rfmTable['order_date'].astype(int)
rfmTable.rename(columns={'order_date': 'recency', 
              'order_id': 'frequency', 
              'grand_total': 'monetary_value'}, inplace=True)
rfmTable.head()

#                  frequency  recency  monetary_value
# customer                                           
# Aaron Bergman            3      415             887
# Aaron Hawkins            7       12            1744
# Aaron Smayling           7       88            3050
# Adam Bellavance          8       54            7756
# Adam Hart               10       34            3249

# R、F、Mのそれぞれについて4段階でスコア付けをする関数を定義
def pct_rank_qcut(series, n):
    edges = pd.Series([float(i) / n for i in range(n + 1)])
    f = lambda x: (edges >= x).argmax()
    return series.rank(pct=1).apply(f)

# Recency
rfmTable['rec_dec'] = pct_rank_qcut(rfmTable['recency'], 4)

# Frequency(数が大きなものを1、小さなものを4とランク付け)
freq_dec = pct_rank_qcut(rfmTable['frequency'], 4)
rfmTable['freq_dec'] = 5 - freq_dec

# Monetary(数が大きなものを1、小さなものを4とランク付け)
mv_dec = pct_rank_qcut(rfmTable['monetary_value'], 4)
rfmTable['mv_dec'] = 5 - mv_dec

# R、F、Mの3つを組合せて、RFMスコアを作成
rfmTable['RFMClass'] = rfmTable.rec_dec.map(str) + rfmTable.freq_dec.map(str) + rfmTable.mv_dec.map(str)
rfmTable.head()

#                  frequency  recency  monetary_value  rec_dec  freq_dec  \
# customer                                                                 
# Aaron Bergman            3      415             887        4         4   
# Aaron Hawkins            7       12            1744        1         2   
# Aaron Smayling           7       88            3050        3         2   
# Adam Bellavance          8       54            7756        2         2   
# Adam Hart               10       34            3249        2         1   

#                  mv_dec RFMClass  
# customer                          
# Aaron Bergman         4      444  
# Aaron Hawkins         3      123  
# Aaron Smayling        2      322  
# Adam Bellavance       1      221  
# Adam Hart             2      212  

# Recencyの4つのグループにつき、購入金額の平均を比較
rec_dec_m = rfmTable.groupby(['rec_dec'])['monetary_value'].mean()
rec_dec_m.plot(kind='bar')

# Frequencyの4つのグループにつき、購入金額の平均を比較
freq_dec_m = rfmTable.groupby(['freq_dec'])['monetary_value'].mean()
freq_dec_m.plot(kind='bar')

Recencyに対するチャート(縦軸:購入金額の平均)
f:id:nami3373:20160919233951p:plain

Frequencyに対するチャート(縦軸:購入金額の平均)
f:id:nami3373:20160919233956p:plain