RFM分析は、過去に書いたデシル分析の拡張です。
金額、行動頻度、最近行動タイミングの3つの属性から、ユーザーをセグメント分けします。
分析と言っても、ここから示唆を出すのは難しいですが、、、
たいていの使い方としては、先にRFMの課題レベルを優先順位づけしておき、
それらに基づいて、3つを掛け合わせたグループの優先順位を決定、
施策をうつグループを決定する、と言う感じになります。
基本プロセス
手順としては、
- id✖️日付✖️売上のデータの準備
- 上記からidごとの、売上、最新日指標、間隔指標の算出
- グループへの分割(可能ならグループの詳細分析)
となります。
1. データの準備
Userクラスを作ってシミュレーションデータを発生させました。
細かい関数の説明は、前記事↓を参照してください。
esu-ko.hatenablog.com
import pandas as pd import random import numpy as np class User: """ ユーザー行動をシミュレーションしてデータを発生させるクラス """ def __init__(self,idx): self.idx = idx # 最後に売上が上がった日をランダムに生成し、それをもとに最初に会計した日も生成 self.last_date = random.choice(pd.date_range(start='2020-04-01',end='2020-06-30')) self.start_date = random.choice(pd.date_range(start='2020-01-01',end=self.last_date)) # 売上が立つ日をランダムに選択 self.freq = random.choice([3,7,14]) # 売上の金額をベース(1500) + ランダム分で生成 self.sales = random.gauss(2000,1000) + 1500 def action_log(self): """ 初めて売上が立つ日から最後の日までをループし、購買行動データを作成 """ ids = [] dates = [] sales = [] for i,d in enumerate(pd.date_range(start=self.start_date,end=self.last_date)): if i == 0 or i % self.freq == 0 or d == self.last_date: ids.append(self.idx) dates.append(d) sales.append(round(random.gauss(self.sales,700))) return pd.DataFrame({'id':ids,'date':dates,'sales':sales}) logs = [] for u in [User(i) for i in range(100)]: logs.append(u.action_log()) df = pd.concat(logs)
2.idごとの、売上、最新日指標、間隔指標の算出
id単位で売上を集計しつつ、 * 最新日: ここでは現状を2020/07/01として、そこから何日まえか * 間隔指標: 売上日数を最初に売上した日 ~ 最後に売上した日の日数で割ったもの とをつくります。
そのために、最初の集計の段階で、最初の売上日、最後の売上日、売上日数も作成しておきます。
# ユーザー単位に集計 agg_df = df.groupby('id').agg({'date':[min,max,np.size],'sales':[sum]}) agg_df.columns = ['date_min','date_max','sales_cnt','total_sales'] # 売上以外の指標をユーザー単位で作成 agg_df['date_range'] = list(map(lambda x : x.days,(agg_df['date_max'] - agg_df['date_min']))) agg_df['freq'] = agg_df['date_range']/agg_df['sales_cnt'] agg_df['rec'] = list(map(lambda x : x.days,agg_df.date_max.apply(lambda x : pd.to_datetime('2020-07-01') - x)))
3. グループへの分割(可能ならグループの詳細分析)
グループ分けをする場合は、
グループ内のユーザー数が同数になる場合と、
指標ないの範囲が等しくなる場合があります。
今回は、施策範囲を決めるために、
ユーザー数が同数になるようにしました。
(ただしfrmからグループを分けると偏りが出るので、最終的なユーザー数を出すのは重要です。
rfm_df = agg_df.loc[:,['total_sales','freq','rec']] rfm_df['m'] = pd.qcut(rfm_df.total_sales,3,[ 'm' + str(i) for i in range(3)]) rfm_df['r'] = pd.qcut(rfm_df.rec,3,[ 'r' + str(i) for i in range(3)]) rfm_df['f'] = pd.qcut(rfm_df.rec,3,[ 'f' + str(i) for i in range(3)])
このあと
ここまでは、分析というよりデータ処理の範囲でした。
このあと、それぞれがどんな属性かを見るために、、別の属性を結合し、
frmを組み合わせた分類グループを目的変数にした決定木分析を行うなどが有効です。
このとき用いる属性は、RFMを決定する行動とは異なる行動から作られた属性や、
FRM行動と直接的な関係性がない属性を使わないと、当たり前の結果しかでてこなくなるので注意が必要です。
この辺りはRの本ですが、こちらなどもご参考ください。(クリックするとamazonに飛びます)
またpythonの決定木に関しては、こちらも読んでいただけると幸いです。