0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Online Retailのデータを用いて、RFM分析を実装してみた

Last updated at Posted at 2025-03-04

はじめに

今回は、「ChatGPTにハンズオンを作らせてみた」の第11弾で、Online Retailのオープンデータを用いて、RFM分析の実装を練習しました。

第10弾はこちら↓

RFM分析

最近の購入(Recency)」、「購入頻度(Frequency)」、「購入金額(Monetary)」の3つの軸を用いて顧客を評価し、マーケティング戦略を最適化するための手法です。

使用データ

今回は、UCI Machine Learning RepositoryからOnline Retailをダウンロードして、それを利用しました。

各変数の説明はこちらです。

変数 説明
InvoiceNo 注文番号
StockCode 商品コード
Description 商品名
Quantity 購入数量
InvoiceDate 注文日時
UnitPrice 単価
CustomerID 顧客ID
Country

使用コード・分析結果

import pandas as pd

# データの読み込み
data = pd.read_csv('Online Retail.csv')

顧客IDがないレコードを削除したうえで、「最終購入からの経過日数」「購入回数」「総購入金額」を算出します。

df = data.dropna(subset=['CustomerID'])
df['InvoiceDate'] = pd.to_datetime(df['InvoiceDate'])

df = df[~df['InvoiceNo'].astype(str).str.contains('C', na=False)]

df['TotalPrice'] = df['Quantity'] * df['UnitPrice']

latest_date = df['InvoiceDate'].max()

rfm = df.groupby('CustomerID').agg({
    'InvoiceDate': lambda x: (latest_date - x.max()).days,  # Recency(最終購入からの経過日数)
    'InvoiceNo': 'nunique', # Frequency(購入回数)
    'TotalPrice': 'sum' # Monetary(総購入金額)
})

rfm.columns = ['Recency', 'Frequency', 'Monetary']

RFMスコアを算出します。

# RFMスコアのランク(1〜5のスコア付け)
rfm['R_score'] = pd.qcut(rfm['Recency'], 10, labels=[10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
rfm['F_score'] = pd.qcut(rfm['Frequency'].rank(method='first'), 10, labels=[1, 2, 3, 4, 5, 6, 7, 8, 9,10])
rfm['M_score'] = pd.qcut(rfm['Monetary'], 10, labels=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

標準化したうえで、階層クラスタリングを実装します。今回は、4つに分類しました。

from sklearn.preprocessing import StandardScaler
import scipy.cluster.hierarchy as sch
import matplotlib.pyplot as plt

# RFMスコアに基づいたデータの前処理
# 必要なカラムだけ抽出して標準化
rfm_data = rfm[['R_score', 'F_score', 'M_score']].astype(int)  # RFMスコアを整数型に変換

# 標準化(スケールを統一するため)
scaler = StandardScaler()
rfm_scaled = scaler.fit_transform(rfm_data)

# 階層クラスタリングを実行(距離行列を計算)
linked = sch.linkage(rfm_scaled, method='ward')  # 'ward'は分散最小化法

# デンドログラムの作成
plt.figure(figsize=(10, 7))
sch.dendrogram(linked)
plt.title("Dendrogram")
plt.xlabel("Customer Index")
plt.ylabel("Distance")
plt.show()

# クラスタ数を決めてクラスタリングを行う
# ここでは4つのクラスタに分ける例です
from scipy.cluster.hierarchy import fcluster
clusters = fcluster(linked, 4, criterion='maxclust')

# クラスタ情報を元のデータフレームに追加
rfm['Cluster'] = clusters

# 結果の確認
rfm[['R_score', 'F_score', 'M_score', 'Cluster']].head()

クラスタごとの統計量から、それぞれの特徴を考察します。

# RFMスコアを整数型に変換
rfm['R_score'] = rfm['R_score'].astype(int)
rfm['F_score'] = rfm['F_score'].astype(int)
rfm['M_score'] = rfm['M_score'].astype(int)

# クラスタごとの統計量を確認
cluster_summary = rfm.groupby('Cluster').agg({
    'R_score': 'mean', 
    'F_score': 'mean', 
    'M_score': 'mean',
    'Cluster': 'count'
})

cluster_summary
Cluster R_score F_score M_score Count
1 7.6287 3.2004 3.0844 474
2 2.6947 2.4148 2.8105 1261
3 4.1413 6.4543 6.3308 1182
4 8.4810 8.2089 7.9986 1422
  • Cluster 1(R:7.63, F:3.20, M:3.08)
    • Recencyが高く、比較的最近購入していることを示しています。
    • FrequencyとMonetaryはやや低めで、購入頻度や金額は低めだと考えられます。
    • Cluster 1の顧客は、最近入ってきた新規顧客である可能性が高いです。
  • Cluster 2(R:2.69, F:2.41, M:2.82)
    • Recency、Frequency、Monetaryともに最も低い。
    • Cluster 2の顧客は、しばらく購入していない離脱顧客である可能性が高いです。
  • Cluster 3(R:4.14, F:6.45, M:6.33)
    • Recencyは中程度ですが、FrequencyとMonetaryはやや高めであることから、頻繁に高額購入を行っている可能性があり、非常に価値の高い顧客である可能性が高いです。
    • Cluster 3は、中程度の頻度で高額購入をしている優良顧客である可能性が高いです。
  • Cluster 4(R:8.48, F:8.21, M:8.00)
    • Recency、Frequency、Monetaryともに最も高く、頻繁に購入しているグループになります。
    • Cluster 4は、頻繁に購入しているリピーターである可能性が高いです。

おわりに

今回は、マーケティング領域で有用なRFM分析を練習しました。
各クラスタの考察がまだまだ浅い気がしますが、概念の理解と実装ができたので、ひとまずOKとしておこうと思います

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?