アソシエーション分析のちょい復習
動機
最近こんな本を購入しました。
www.shoeisha.co.jp
第I部の「データアナリティクスの基礎」は、データ分析のプロジェクトの全体像に触れていて、データ分析のプロジェクトをどう進めていくかについて整理するのには良いのかな、と思いました*1。後半部分の分析内容は結構あっさりしていて、すでに専門的なスキルを持っている方向けではなさそうです。
この書籍の第8章で、Rを使ったアソシエーション分析を取り扱っています。これは、マーケティングの分野でよく使用される手法です。顧客の購買履歴から、「商品Aを買った人は商品Bを買う確率が高い」といった関係性を見つけ出します。自分は、業務では予測分析がメインなので、そういえば久しくこういった手法に触れてなかったな…と感じました。というわけで、復習の一環で簡単にデモしてみようと思います*2。
アソシエーション分析の説明は、例えば以下のサイトが参考になるかと思います。
sinhrks.hatenablog.com
sinhrks.hatenablog.com
実務では、今回使用するサンプルデータのような形式に簡単にまとめられない場合があるので、前処理も含めた解説は非常にためになります。
本当はPythonでやろうと思ったけど、自分の環境ではうまく構築できなかった
Pythonでは、Orangeというものでアソシエーション分析が可能ということで、pipでOrange(何も指定しないとVer. 2.7.8)をインストールしようとしました。しかし、setup.pyのビルドでコケてしまい、結局解消せず*3。大本のページ(Orange Data Mining)を見ると、最新版はVer. 3.3.7とのこと。pip経由だと、Orange3と指定するとインストールできそうなので実行。こちらはインストールに成功しましたが、アソシエーション分析に必要なメソッドが無い。OrangeでPythonからAprioriを動かす - Qiitaを見ると、どうやら本当に無い模様。
というわけで、いったんPythonで進めるのは保留にして、Rでデモをやるだけにします。
Rの{arules} + {arulesVIz}を使って分析
Rでアソシエーション分析を行う場合、例えば{arules}というパッケージがあります。今回は、このパッケージを使用していきます。
{arules}のインストール
if(!require(arules)){ install.packages("arules", dependencies = TRUE) } require(arules)
データセットの読み込み
店舗の30日間のPOSデータを使用します。9835トランザクション、196カテゴリからなるデータで、「milk(牛乳)」、「root vegitables(根菜類)」といった商品の併売情報が入っています。
data(Groceries) Groceries # 出力 transactions in sparse format with 9835 transactions (rows) and 169 items (columns)
先頭の数行を確認してみます。併売情報を出力するのに、inspect()を用います。
inspect(head(Groceries)) # 出力 items 1 {citrus fruit, semi-finished bread, margarine, ready soups} 2 {tropical fruit, yogurt, coffee} 3 {whole milk} 4 {pip fruit, yogurt, cream cheese , meat spreads} 5 {other vegetables, whole milk, condensed milk, long life bakery product} 6 {whole milk, butter, yogurt, rice, abrasive cleaner}
このようなデータを作ったり、アクセスしたりするのは一筋縄ではいかないのですが、ここではうまくトランザクションデータが手に入っているという状況で先に進みます。
summaryで基本統計量の確認
summary(Groceries) # 出力 transactions as itemMatrix in sparse format with 9835 rows (elements/itemsets/transactions) and 169 columns (items) and a density of 0.02609146 most frequent items: whole milk other vegetables rolls/buns soda yogurt 2513 1903 1809 1715 1372 (Other) 34055 element (itemset/transaction) length distribution: sizes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 2159 1643 1299 1005 855 645 545 438 350 246 182 117 78 77 55 46 29 18 19 20 21 22 23 24 26 27 28 29 32 14 14 9 11 4 6 1 1 1 1 3 1 Min. 1st Qu. Median Mean 3rd Qu. Max. 1.000 2.000 3.000 4.409 6.000 32.000 includes extended item information - examples: labels level2 level1 1 frankfurter sausage meat and sausage 2 sausage sausage meat and sausage 3 liver loaf sausage meat and sausage
出力結果の意味は以下です。
- most frequent items : 頻度(=商品が売れた数)
- element (itemset/transaction) length distribution : 1トランザクションで購入した商品の数
- Min, 1st Qu., Median, Mean, 3rd Qu., Max : 最小値、第一四分位数、中央値、平均値、第三四分位数、最大値
商品ごとのヒストグラム
先程の要約だと、商品ごとの頻度の情報が十分ではありませんでした。ここでは、購入された商品に対して相対出現頻度によるヒストグラムを出力します。これは、itemFrequencyPlot()で実行できます。全商品を可視化すると複雑になるので、引数のsupportで支持度4%以上の商品のみに限定しています。
# 目盛りを無駄にメイリオに設定 quartzFonts(Hir = c("HiraMaruPro-W4", "HiraMaruProN-W4", "Meiryo", "HiraMinProN-W3")) itemFrequencyPlot(Groceries, support = 0.04, cex.names = 0.7, col = "red", family = "Hir", font = 3)
アソシエーション分析の実行
apriori()で実行できます。support(支持度)とconfidence(確信度)は、それぞれ手で0.5%以上、1%以上をしきい値としました。
rules <- apriori(Groceries, parameter = list(support = 0.005, confidence = 0.01)) # 表示結果 Apriori Parameter specification: confidence minval smax arem aval originalSupport support minlen maxlen target ext 0.01 0.1 1 none FALSE TRUE 0.005 1 10 rules FALSE Algorithmic control: filter tree heap memopt load sort verbose 0.1 TRUE TRUE FALSE TRUE 2 TRUE Absolute minimum support count: 49 set item appearances ...[0 item(s)] done [0.00s]. set transactions ...[169 item(s), 9835 transaction(s)] done [0.00s]. sorting and recoding items ... [120 item(s)] done [0.00s]. creating transaction tree ... done [0.00s]. checking subsets of size 1 2 3 4 done [0.00s]. writing ... [2138 rule(s)] done [0.00s]. creating S4 object ... done [0.00s].
この条件だと併売に関する2138個のルールが出来上がります。
特定の商品に注目した場合
アソシエーションのルールは、「X ならば Y」という形になっています。作成したルールを用いて、Yを固定したときにXがどのようなものがあるかを確認してみます。
# Y = "onions"(たまねぎ)にしてみる onionRules <- subset(rules, subset = rhs %in% "onions") # リフト値が高い順に表示 inspect(sort(onionRules, by = "lift")) # 出力 lhs rhs support confidence lift 1304 {root vegetables,other vegetables} => {onions} 0.005693950 0.12017167 3.8750440 1307 {other vegetables,whole milk} => {onions} 0.006609049 0.08831522 2.8478038 316 {root vegetables} => {onions} 0.009456024 0.08675373 2.7974523 324 {other vegetables} => {onions} 0.014234875 0.07356805 2.3722681 308 {whipped/sour cream} => {onions} 0.005083884 0.07092199 2.2869434 310 {citrus fruit} => {onions} 0.005592272 0.06756757 2.1787771 314 {tropical fruit} => {onions} 0.005693950 0.05426357 1.7497776 312 {bottled water} => {onions} 0.005897306 0.05335787 1.7205725 320 {yogurt} => {onions} 0.007219115 0.05174927 1.6687019 326 {whole milk} => {onions} 0.012099644 0.04735376 1.5269647 322 {rolls/buns} => {onions} 0.006812405 0.03703704 1.1942927 47 {} => {onions} 0.031011693 0.03101169 1.0000000 318 {soda} => {onions} 0.005287239 0.03032070 0.9777183
これより「root vegetables(根菜類), other vegetables(他の野菜)」やroot vegetables(根菜類), whole vegetables(牛乳)」といった条件がonions(たまねぎ)に結びつくものがリフト値が高い(単に玉ねぎを買うよりよりもXを買ってさらにYを買う確率が高い)ことがわかります。
結果の可視化
{arulesViz}のインストール
if(!require(arulesViz)){ install.packages("arulesViz", dependencies = TRUE) } require(arulesViz)
(図が単純になるように)ルールを再設定
rules <- apriori(Groceries, parameter = list(support = 0.004, confidence = 0.5))
以下では、有用そうな図をいくつか紹介していきます。
散布図
散布図は、method = "scatterplot"で指定します。
graphics::plot(rules, method = "scatterplot")
横軸が支持度、縦軸が確信度で、点の色が赤に近いほどリフト値が高くなっています。これより、例えばリフト値が高い領域がわかり、パラメータ設定の参考にすることができます。
バブルチャート
method = "grouped"と指定することで、XとYの関係を直観的(丸の大きさと色)で表現できます。
graphics::plot(rules, method = "grouped")
横軸がアソシエーションの左辺(X)、縦軸が右辺(Y)、支持度の大きさは丸のサイズ、リフト値の大きさは色の濃さで表されています。
アソシエーショングラフ
有向グラフ形式(矢印で関係が表現されているグラフ)で表現することも可能です。表示を簡単にするため、リフト値の上位10項目のみに着目します。method = "graph"で有向グラフを表現できます。
# リフト値の高い順に10項目 rules_high_lift <- head(sort(rules, by = "lift"), 10) graphics::plot(rules_high_lift, method = "graph", control = list(type = "items"))
herbsを購入した人は、root vegetablesを購入する可能性が高い(?)などが表示されます。
実はWindowとMacでこの表示が異なるそうで、Windowsはマウス操作で移動ができるそうです。