【Python】販売データに基づくアソシエーション分析【コードで解説】

Python
この記事は約8分で読めます。

今回はアソシエーション分析についてお話しさせていただきます。
アソシエーション分析とは、機械学習の中でも教師なし学習の一つであり教師データを必要としません。
販売データから一緒に購入されている商品の関連性を見つける分析手法です。
主にマーケティングではアップセル、クロスセルなど、客単価や注文点数を向上させるために利用されます。

一緒に購入される商品がわかると、店舗の陳列棚のレイアウト変更のヒントになり、
ECサイトであれば、一緒に購入されている商品として顧客におすすめすることができます。

データはこちらを利用します。

E-Commerce Data
Actual transactions from UK retailer

pluginはmlxtendを利用します。aprioriアルゴリズムで解いていきます

Association rules - mlxtend
A library consisting of useful tools and extensions for the day-to-day data science tasks.

コードの準備

ほとんどサンプルコードのままです、利用例としてご紹介します。

import pandas as pd

df = pd.read_csv('/ecommerce-data/data.csv', encoding="shift-jis")

df.head()

import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori


dataset = df.groupby('InvoiceNo')['StockCode'].apply(list)
dataset

te = TransactionEncoder()
te_ary = te.fit(dataset).transform(dataset)
df2 = pd.DataFrame(te_ary, columns=te.columns_)
frequent_itemsets = apriori(df2, min_support=0.6, use_colnames=True)

frequent_itemsets

from mlxtend.frequent_patterns import association_rules

association_rules(frequent_itemsets, metric="confidence", min_threshold=0.6)

ライブラリのインポート、csv読み込み

import pandas as pd

df = pd.read_csv('/kaggle/input/ecommerce-data/data.csv', encoding="shift-jis")

df.head()

InvoiceNo 請求書番号
StockCode 在庫コード
Description 商品説明
Quantity 数
InvoiceData 請求日付
UnitPrice 価格
CustomerID 顧客ID
Country 国

Aprioriで分類する

Aprioriはざっくりと、
あらかじめ閾値を決めて、計算する対象を減らすアルゴリズムです。
データ数が増えると、その分だけアソシエーションの計算が増えるため
あらかじめ対象数を減らすという考え方です。

from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori

dataset = df.groupby('InvoiceNo')['StockCode'].apply(list)
dataset
InvoiceNo
536365     [85123A, 71053, 84406B, 84029G, 84029E, 22752,...
536366                                        [22633, 22632]
536367     [84879, 22745, 22748, 22749, 22310, 84969, 226...
536368                          [22960, 22913, 22912, 22914]
536369                                               [21756]
                                 ...                        
C581484                                              [23843]
C581490                                       [22178, 23144]
C581499                                                  [M]
C581568                                              [21258]
C581569                                       [84978, 20979]
Name: StockCode, Length: 25900, dtype: object
te = TransactionEncoder()
te_ary = te.fit(dataset).transform(dataset)
df2 = pd.DataFrame(te_ary, columns=te.columns_)
frequent_itemsets = apriori(df2, min_support=0.6, use_colnames=True)

frequent_itemsets

閾値0.6では一つも出力されませんでした。
0.04で36件抽出できました。

supportitemsets
00.040541(20724)
10.062085(20725)
20.040039(20726)
30.050000(20727)
40.045290(20728)
50.051506(21212)
60.046371(21931)
70.045174(22086)
80.041004(22178)
90.055676(22197)
100.045174(22382)
110.050425(22383)
120.042857(22384)
130.047529(22386)
140.045830(22411)
150.083861(22423)
160.048880(22457)
170.046873(22469)
180.044942(22666)
190.040811(22697)
200.043243(22699)
210.056448(22720)
220.041737(22727)
230.047104(22960)
240.045328(22961)
250.041776(22993)
260.048224(23203)
270.040502(23206)
280.042857(23209)
290.044749(23298)
300.065869(47566)
310.043166(82482)
320.056680(84879)
330.082432(85099B)
340.086718(85123A)
350.048417(POST)

データを抽出する

そのままの全データでは結果が上手くアウトプットされないので、
特定の国のデータのみ抽出してからAprioriにかけてみます。

df.Country.value_counts().head(5)

UKのデータが大半ですので、Germanyのデータに絞ってみていきましょう。

df = df[df.Country == 'Germany']

InvoiceNoでピボットテーブルを作成します。
これがバスケットリストとなります。

basket = pd.pivot_table(data=df,index='InvoiceNo',columns='Description',values='Quantity', \
                        aggfunc='sum',fill_value=0)

データをGermanyに限定してAprioriを実行する。

思うように結果が表示されました!
続いてルールを適用します。

リフト値で分類する

metricにliftを指定しています。support(支持度)、confidence(信頼度)、lift(リフト値)から選べます。
リフト値とは商品Aと一緒に商品Bを購入した人の割合を全体のデータから商品Bを購入した人の割合よりどれくらい多いかを表した指標となります。
リフト値が1未満の場合は商品Bが売れている理由は他にあるため1以上のものを抽出させます。ですのでmin_thresholdは1を指定します。

rules_mlxtend = association_rules(frequent_itemsets, metric="lift", min_threshold=1)
rules_mlxtend.head()

antecedentsが商品Aでconsequentsが商品Bとなります。
アソシエーション分析は方向性がありますので気をつけましょう。

例えば、プリンタのインクを購入しようとしている人にプリンタ本体は勧めない
書籍の初級編、上級編で上級編を購入しようとしている人に初級編は勧めないなどです。

さいごに

アソシエーション分析には方向性があり、A>CとC>Aでは信頼度が異なります。

・小説の上中下で下巻を購入している人に上巻を薦める
・ゲームソフトを購入しようとしている人にゲーム機本体を薦める

など、顧客の購買状況に合わせた推薦をするように気をつけましょう。

タイトルとURLをコピーしました