python で GA のデータを、ユーザーあたりのpageviewでセグメント分けする


Pandas で、Google Analytics のデータをセグメント分けしてみます。
以下実施したことを記載します。

前提

以下、前提事項を記載します。

  • clientId を予めカスタムディメンションとして送付しておく
    データセットは、Google Analytics で取得したデータです。
    Google Analytics は デフォルト設定では、どのユーザーのアクセスなのかを識別することができません。
    このため、Google Analytics の cookie を クライアントID として、 カスタムディメンションとして 送信しています。
    Google Analytics の cookie をカスタムディメンションとして送付する方法は、以下の記事が参考になりました。
    2016年の新定番!ユーザーエクスプローラーをもっと活用するための簡単な方法 | 株式会社プリンシプル

  • Google Analytics Spreadsheet Add-on で、データを取得する
    google analytics spreadsheet add-on を使って、Google Analytics からデータを取得します。
    上記の使用方法は、Googleアナリティクスの分析はスプレッドシートのアドオンで全自動化しよう が参考になりました。
    レコメンドに使用するデータセットとして、以下の Metrics、Dimensions を指定しています。
    また、データの取得件数ですが、デフォルトは1000件までです。10000件までは引き上げられるので、10000件を設定しています。

    • Metrics
      • ga:pageviews
    • Dimensions
      • ga:date
      • ga:dimension8 (clientId) を設定しているdimensionになります。ここはそれぞれ変わります。
      • ga:pagePath
  • Google Analytics Spreadsheet Add-on のデータ取得イメージ
    以下のようなデータになります。
    "スプレッドシート抜粋"

  • どんな観点でセグメントをつけるか
    ユーザーあたりのpageviewで、セグメント分けをします。
    1、2-4、5以上という雰囲気で分けます。

セグメント分けの手順

以下、手順でセグメント分けをしていきます。

  1. スプレッドシートからpython へのデータ取り込み
    データの取り込みを実施します。
  2. データの分布を確認する
    セグメント分けの前に、どのくらいの割り合いで分けるか決定するため、データ分布を確認します。
  3. セグメント分け
    実際にデータをセグメント分けします。

スプレッドシートからpython へのデータ取り込み

python へのデータの取り込み、形式変換を実施します。
google スプレッドシートからのデータの取り込みには、gspread を使います。

事前準備

必要なライブラリをインストールします。

python3 -m pip install gspread --user
python3 -m pip install oauth2client --user
python3 -m pip install df2gspread --user
python3 -m pip install pandas --user
python3 -m pip install sklearn --user
python3 -m pip install matplotlib --user
python3 -m pip install plotly --user

スプレッドシートのデータを取得する

以下のコードで、スプレッドシートのデータを取得してデータセットとして使用します。
API にアクセスするための JSON Key の発行が事前に必要になります。
APIの発行方法、gspread の使い方は以下の記事が参考になりました。
[Python] Google SpreadSheetをAPI経由で読み書きする - YoheiM .NET

データ取得、pandas のdataframe に変換するプログラム

以下に記載します。

from oauth2client.service_account import ServiceAccountCredentials
def download_as_df(sheet_id, wks_name):
    from df2gspread import gspread2df as g2d
    # key_file 以下の指定方法だと、notebook と同じディレクトリにあるキーファイルを取得しています。
    key_file = "spreadsheet_api_key.json"
    scope = ['https://spreadsheets.google.com/feeds']
    credentials = ServiceAccountCredentials.from_json_keyfile_name(key_file, scope)    
    df = g2d.download(sheet_id, wks_name=wks_name, col_names=True, row_names=False, credentials=credentials, start_cell = 'A15')
    df = df.sort_values(by='ga:date') 
    return df

# 201710月-201712月のデータを取得する   
df_201710 = download_as_df("1brCpWvk2uofc3MEt-ASb2cuZ-u8Zmx-ICxSTltlbVBQ","ユーザーの行動レポート 201710")
df_201711 = download_as_df("1brCpWvk2uofc3MEt-ASb2cuZ-u8Zmx-ICxSTltlbVBQ","ユーザーの行動レポート 201711")
df_201712 = download_as_df("1brCpWvk2uofc3MEt-ASb2cuZ-u8Zmx-ICxSTltlbVBQ","ユーザーの行動レポート 201712")
# dataframeのマージ
import pandas as pd
df = pd.concat([df_201710, df_201711, df_201712])

データの分布を確認する

以下、参考にしながら進めました。
Pandasでデータ集計をする際に最低限覚えておきたいメソッド - Qiita

ユーザのPageView の分布を計算する

# clientID 単位にページVIEWを集計
df_groupby = df.groupby("ga:dimension8",as_index=True)
# groupby した結果の ga:pageviews をカウント カウント結果をソートする
df_count_page_views = df_groupby.agg({"ga:pageviews": "count"}).sort_values("ga:pageviews",ascending=False)

# データの分布をvalue_counts()で出力、結果をソートする
series_counts = df_count_page_views["ga:pageviews"].value_counts().sort_index(0)
series_counts
1      10286
2       1082
3        301
4        127
5         67
6         29
7         27
8         10
9          8
10         7
11         7
12         4
13         5
14         4
15         2
16         1
17         2
18         3
20         4
21         1
23         1
24         1
25         1
28         1
33         1
43         1
74         1
177        1
Name: ga:pageviews, dtype: int64

plotlyで折れ線グラフを表示

# plotlyで折れ線グラフを表示
import plotly
plotly.offline.init_notebook_mode(connected=False)
plotly.offline.iplot([{
    'x': series_counts.index,
    'y': series_counts.values,
    'name': "ga:pageviews"
}], filename='データ分布', show_link=False, config={"displaylogo":False, "modeBarButtonsToRemove":["sendDataToCloud"]})

折れ線グラフ

plotly で円グラフ表示

# ploty で円グラフ表示
import plotly
import plotly.graph_objs

labels = series_counts.index
values = series_counts.values

trace = plotly.graph_objs.Pie(labels=labels, values=values)
plotly.offline.init_notebook_mode(connected=False)
plotly.offline.iplot([trace], filename='basic_pie_chart')

円グラフ

セグメント分けをする

ほとんど、1ページを見に来て帰る人が多いことがわかります。
エルボー法でクラスタ数をいくつにすればよいのか確認してみます。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display, HTML # Jupyter notebook用
from sklearn.cluster import KMeans
%matplotlib inline
def plot_elbow(array):
    distortions = []
    for i  in range(1,11):                # 1~10クラスタまで一気に計算 
        km = KMeans(n_clusters=i,
                    init='k-means++',     # k-means++法によりクラスタ中心を選択
                    n_init=10,
                    max_iter=300,
                    random_state=0)
        km.fit(array)                         # クラスタリングの計算を実行
        distortions.append(km.inertia_)   # km.fitするとkm.inertia_が得られる
    plt.plot(range(1,11),distortions,marker='o')
    plt.xlabel('Number of clusters')
    plt.ylabel('Distortion')
    plt.show()
array = np.array([series_counts.index,
                       series_counts.values,
                       ], np.int32)
array = array.T
plot_elbow(array)

output_13_0.png

クラスタ数は2つに分けるのが、よさそうです。
クラスタ数2でクラスタリングします。

pred = KMeans(n_clusters=2).fit_predict(array)
pred
array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0], dtype=int32)

2回以上アクセスしているグループを更にクラスタリングします。

del series_counts[1]
array = np.array([series_counts.index,
                       series_counts.values,
                       ], np.int32)

array = array.T
plot_elbow(array)

output_17_0.png

pred = KMeans(n_clusters=2).fit_predict(array)
pred
array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0], dtype=int32)

2回と、3回以上にわかれました。
3回以上を更にクラスタリングします。

del series_counts[2]
array = np.array([series_counts.index,
                       series_counts.values,
                       ], np.int32)

array = array.T
plot_elbow(array)

output_20_0.png

pred = KMeans(n_clusters=4).fit_predict(array)
pred
array([1, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
       3, 3, 2], dtype=int32)

3回のクラスタリングとデータ削除で以下のセグメントを得ました。

  • pageviewが1のグループ
  • pageviewが2のグループ
  • pageviewが3-4のグループ
  • pageviewが5-74 (5以上99以下) のグループ
  • pageviewが74以上(100以上)のグループ

Google Analytics から、セグメントの設定が可能なので、上記をセグメントして設定してみようと思います。

その他考慮したほうが良さそうな観点

ユーザーあたりのpageviewでセグメントを設定してみました。
以下、実施しながら考慮したほうがいいかもしれないと思った観点を記載します。

  • pageview ではなく、セッション数を使う。
  • 日をまたいだアクセス 初回アクセス後に別の日に同じページを訪れているか。

以上です。

コメント