この記事はGoogle Analytics 4ではなく、Universal Analyticsを対象としています。
Rでアソシエーション分析したい
多変量解析の手法のひとつであるアソシエーション分析を実データで学習しておりまして、アクセスログからデータ抽出・前処理するまでの流れをメモ程度に残しておきます。
この記事はGoogle Analytics 360(BigQuery Export)の利用を前提としています。
アソシエーション分析とは
バスケット内のアイテム間の意味のある関係を調べる分析手法です。「XXが購入されるとYYも購入される傾向にある」といったようなアイテムごとの組み合わせの規則を抽出することができます。
データ抽出
分析に用いるデータのトランザクション(共起するデータポイント)の単位について、以下2つの粒度で抽出してみます。
- セッション内でのイーコマーストランザクション(SKU)
- セッション内で表示されたページ(第二階層)
今回の場合はBigQueryからデータ抽出・CSVファイル出力し、R側で最終的にトランザクション型のデータを用意することになります。
1. SKU単位の場合
セッション(visitId)ごとの購入(SKU)を1つのトランザクションとします。
※抽出元のサービスが1度に1つの商品しか購入できないため、「1セッションを1つのトランザクション」として捉えています。一度に複数購入可能であればこの限りではありません。
SELECT
visitId,
product.productSKU AS sku
FROM
`project_name.dataset_name.ga_sessions_YYYYMMDD`,
UNNEST(hits) AS hits,
UNNEST(hits.product) AS product
以下のようなテーブルが抽出できるイメージです。
行 | visitId | sku |
---|---|---|
1 | 1585704179 | ABC00000149 |
2 | 1585674923 | DEF00001609 |
3 | 1585701501 | GHI00004228 |
2. ページ単位の場合
セッションごとの閲覧ディレクトリ(第2階層/pagePathLevel2)を1つのトランザクションとします。/
の文字列は列名としては扱えないので、あらかじめ除去しておきます。
WITH
raw_data AS (
SELECT
visitId,
hits.page.pagePathLevel2 AS path
FROM
`project_name.dataset_name.ga_sessions_YYYYMMDD`,
UNNEST(hits) AS hits
WHERE
hits.type = "PAGE"),
fixed_data AS(
SELECT
visitId,
IF
(path = "/",
"top_page",
path) AS path
FROM
raw_data)
SELECT
visitId,
REGEXP_REPLACE(path, "/", "") AS path,
FROM
fixed_data
GROUP BY
visitId,
path
以下のようなテーブルが抽出できるイメージです。
行 | visitId | path |
---|---|---|
1 | 1585704179 | top_page |
2 | 1585674923 | faq |
3 | 1585701501 | products |
Rで前処理
今回必要なライブラリを読み込みます。
library(tidyverse) # データハンドリング
library(arules) # アソシエーションルールの検出
library(arulesViz) # アソシエーションルールの可視化
library(dummies) # one-hotエンコード
ローカル環境の処理能力の限界もありますので、前処理は可能な限りBigQueryやDataprepなどクラウド側の計算資源を活かした方が良さそうです。
CSVファイルをデータフレームとして読み込み、one-hotエンコーディングし、transaction型へキャストします。
raw_data <- read_csv("src/xxx_by_visitid.csv") %>%
distinct(visitId,sku) %>%
as.data.frame() #dummiesがtibbleを扱えないためdataframeにキャスト
df.one_hot <- dummy.data.frame(raw_data,sep = "_")
colnames(df.one_hot) = str_replace(colnames(df.one_hot), 'column_name_', '')
df.one_hot <- df.one_hot %>%
group_by(visitId) %>%
summarise_each(funs(sum)) %>%
select(-visitId)
d.transaction <- as(as.matrix(df.one_hot), "transactions")
aprioriの実行
apriori()
を実行してアソシエーションルールを検出します。parameter
での支持度、確信度の閾値は 検出されるルールの数やマシンの計算資源に合わせて適宜調整します。
d.ap <- apriori(d.transaction, parameter = list(supp = 0.001, conf = 0.1))
d.ap
にルール集合を代入しているのででinspect()
を用いてアソシエーションルールの確認ができます。ここではリフト値の高い順に10件抽出してみます。
inspect(head(sort(d.ap, by = "lift"),10))
## lhs rhs support confidence coverage
## [1] {category,game,top10} => {market} 0.8035937 0.9778611 0.8217872
## [2] {enquete,top10} => {market} 0.8010750 0.9761986 0.8206065
## [3] {category,game,product} => {market} 0.8049768 0.9743712 0.8261500
## [4] {category,game} => {market} 0.8096207 0.9738291 0.8313787
## [5] {game,product,top10} => {market} 0.8071919 0.9730396 0.8295571
## [6] {game,top10} => {market} 0.8123531 0.9723680 0.8354379
## [7] {category,product,top10} => {market} 0.8955393 0.9723114 0.9210417
## [8] {category,top10} => {market} 0.9021848 0.9716029 0.9285530
## [9] {game,market,top10} => {category} 0.8035937 0.9892172 0.8123531
## [10] {game,market,product} => {category} 0.8049768 0.9884297 0.8143996
## lift count
## [1] 1.057983 71466
## [2] 1.056185 71242
## [3] 1.054208 71589
## [4] 1.053621 72002
## [5] 1.052767 71786
## [6] 1.052040 72245
## [7] 1.051979 79643
## [8] 1.051213 80234
## [9] 1.050876 71466
## [10] 1.050039 71589
lhs(left-hand-side)
が条件部、rhs(right-hand-side)
が結論部となり、「lhsが含まれるトランザクションにはrhsが含まれやすい」と判断できます。
ここでの結果はどれもリフト値が1に近いため、ルールの重要度が高いと判断するのは難しそうです。
ルール分布をplotで描画
plot()
では支持度と信頼度の散布図を描画することができます。
plot(d.ap)
medhod
にgrouped
を指定するとルールをグルーピングすることができます。
plot(d.ap, method = "grouped", control = list(k=10))
method
にgraph
を指定するとigraphによるグラフ描画が可能です。
plot(d.ap, method = "graph", control = list(type = "items"))
円の大きさがルールの支持度、濃淡がリフト値を表しています。アイテムからルールに向かう矢印は「そのアイテムが左側」であり、ルールからアイテムに向かう矢印は「そのアイテムが右側」であることを意味しています。
interactive
にTRUE
を指定するとXQuartsを利用してインタラクティブな描画が可能になります。
plot(d.ap,method = "graph", control = list(type="items"), interactive = TRUE)
このグラフからアソシエーションルールの向きの意味を解釈するのは難しそうですが、クラスタのパターン発見という意味では有意義な結果が得られそうです。例えば事前の知識がない状態でアクセスログを確認する場合に、ざっくりとした行動パターンのクラスタは把握できるかもしれません。また「導線設置」の施策があったとして、その施策の前後のグラフを比較することでクラスタに変化があったかどうかを可視化できそうです。
おわりに
実際にアソシエーションルールを分析したところSKUについてはある程度納得の行く結果が得られたものの、同時購入ではなくセッション内での購入ベースとなるため、共起の重要性が低そうな印象もありました。
またページパスについてはサイトにおいてある程度ユーザーの行動が決まっていることもあり、有意味なルールを見つけることはできませんでした。ただ、グラフ描画によるクラスタ理解は活用できそうに思えました。