Rtoasterのデータを格納したinsight+のRtoasterテーブルをAIStudioで読み込み、Auto Modelを試します。
※データはダミーです。
(1)アクセスログの離脱ページを分析する
(2)購入ユーザーの特徴を分析する
使用するデータはRtoaster テーブルの下記2つのテーブルです。スキーマやデータの詳細に関しましてはこの仕様書をご確認ください。
・accesslog(Webアクセスログ)
・conversionlog(Webコンバージョンログ)
データはinsight+からGCS(GCPのCloud Storage)へと出力しておきました。そのデータを GCS から
ダウンロードしてローカルから読み込むかもしくは接続先「Google Cloud Services」を作成して GCS から直接 AIStudio へデータを読み込みます。
(1)アクセスログの離脱ページを分析する
データ「accesslog(Webアクセスログ)」には「is_exit」カラムが存在します。このカラムは離脱ページフラグを示しており、該当レコードでユーザーが同一セッション中にサイトを離れたページであることを示します。このフラグがついているレコードの特徴をAuto Model で分析します。
データ「accesslog(Webアクセスログ)」を読み込み、Auto Model ビューで選択します。
分析の種別は「Predict」、目的変数は「is_exit」を選択します。
目的変数の比率です。ここの比率自体は今回は特に意識しません。is_exitは直帰でない限り1アクセスにつき複数の値「1」とアクセス最後の「0」が組み合わされるため、「1」の方が少ないことが自然です。
説明変数を選択します。不要な列を削除します。
・Auto Modelが不適と判断しているカラムはそのまま未選択とします。
・「is_entrance」はランディングページフラグであり確実にis_exitではないことが判明しているため外します。
・「session_id」はセッションごとに振られているuuidですので外します。
・「user_group」はA/Bテスト用のユーザーのグルーピングで今回は特に指定していないため外します。
・「custom_dimensions」はまだ未整備のため外します。
適用するモデルを選択します。今回は下記の設定で試します。
Auto Modelの結果を確認します。途中経過ですが、一般化線形モデルの結果が良いようです。
離脱ページであることを支持する説明変数の要素を確認します。今回のCofficientsは負の値で当該レコードが離脱ページであることを支持しており、逆に正の値で離脱ページではないことを支持しております。「user_agent:requests」「user_agent:python」はpythonのrequestsモジュールからのアクセスを示していますので、おそらく人間でなくシステムが1ページのみアクセスした可能性が高いです。このアクセスは次回の下処理からは外して分析する必要があることがわかりました。
離脱ページではないことを支持する説明変数の要素を確認します。user_agentが一般的なブラウザであること。page_pathに「html」が含まれていることは一般的すぎるため無視します。それを除くと特段示唆はないようです。
今回は目立った成果は得られませんでしたが、データを加工することでもう少し示唆が得られるかもしれません。今回軽くデータを見たことで下記の分析を思いつきました。
・表示される商品を制御しているページのパラメータを商品マスターを用意することでカテゴリー化し、商品カテゴリーも説明変数に加えてみる。
・User_agentを整理してカテゴリー化する。
・Session_idごとにwindow化して直帰のみを判別するフラグを追加する
(2)購入ユーザーの特徴を分析する
データ「accesslog(Webアクセスログ)」とデータ「conversionlog(Webコンバージョンログ)」を加工して購入回数の多いユーザーの特徴を分析します。今回はわかりやすい結果が出るようにデータを操作しておりますのでご留意ください。
今回のアプローチは「accesslog(Webアクセスログ)」と「conversionlog(Webコンバージョンログ)」を合体させ、下記の説明変数を作成しました。
・num_pages_to_conversion:ランディングページまたは同一セッション中の前回購入から購入までのページ数
・site_enter_to_cv:同一セッション中のランディングページへ訪問した時間から購入までの差(秒)
処理が冗長であるため、pandasで「Execute Python」オペレータに処理を記載しました。画面左の「Read CSV」オペレータで「accesslog(Webアクセスログ)」、「conversionlog(Webコンバージョンログ)」を読み込んでおります。
「Execute Python」オペレータに記載したコード
(ウィンドウ処理の箇所のコードはchat-gptで出力されたコードを参考に作成しました。)
import pandas as pd
from datetime import datetime
def rm_main(df1,df2):
ac_df = df1
cv_df = df2
# 0で欠損値を補完
cv_df['visit_interval'] = cv_df['visit_interval'].fillna(0)
cv_df['subtotal'] = cv_df['subtotal'].fillna(0)
# 欠損値が含まれる行を削除
cv_df = cv_df.dropna(subset=['entrance_site'])
# 変な値や外れ値を除去
cv_df = cv_df[cv_df['subtotal'] > 0]
cv_df = cv_df.dropna(subset=['session_id'])
# 不要な列を削除する
ac_df = ac_df[ac_df['is_well_known_bot'] == 'False']
ac_df = ac_df.drop(['ip_addr','referring_site','user_agent','via_sdk',
'device_type','custom_dimensions','page', 'site', 'user_group'
], axis=1)
# セッションidのないレコードを削除
ac_df = ac_df.dropna(subset=['session_id'])
# 購入日時とサイトに訪問した日時の差を求める
cv_df['date'] = pd.to_datetime(cv_df['date'], format='%Y-%m-%d %H:%M:%S.%f%z', errors='coerce')
cv_df['enter_at'] = pd.to_datetime(cv_df['enter_at'], format='%Y-%m-%d %H:%M:%S.%f%z', errors='coerce')
cv_df = cv_df.dropna(subset=['date','enter_at'])
ac_df['date'] = pd.to_datetime(ac_df['date'], format='%Y-%m-%d %H:%M:%S.%f%z', errors='coerce')
cv_df['site_enter_to_cv'] = cv_df['date'] - cv_df['enter_at']
cv_df['site_enter_to_cv'] = cv_df['site_enter_to_cv'].dt.total_seconds()
cv_df['site_enter_to_cv'] = cv_df['site_enter_to_cv'].fillna(0)
ac_df["data_type"] = "access_log"
cv_df["data_type"] = "conversion"
cv_df['is_entrance'] = None
cv_df['is_exit'] = None
ac_df['conversion_page']=None
ac_df['subtotal']=None
ac_df['item_code']=None
ac_df['enter_at']=None
ac_df['entrance_site']=None
ac_df['entrance_page_path']=None
ac_df['entrance_query_param']=None
ac_df['entrance_referring_page']=None
ac_df['entrance_referring_page_path']=None
ac_df['site_enter_to_cv']=None
cv_df = cv_df.reindex([
"data_type",
'date',
'session_id',
'user_id',
'user_id_type',
'page_path',
'query_param',
'referring_page',
'referring_page_path',
'referring_query_param',
'is_new_visit',
'is_well_known_bot',
'visit_interval',
'is_entrance',
'is_exit',
'conversion_page',
'subtotal',
'item_code',
'enter_at',
'entrance_site',
'entrance_page_path',
'entrance_query_param',
'entrance_referring_page',
'entrance_referring_page_path',
'site_enter_to_cv'], axis='columns')
ac_df = ac_df.reindex([
"data_type",
'date',
'session_id',
'user_id',
'user_id_type',
'page_path',
'query_param',
'referring_page',
'referring_page_path',
'referring_query_param',
'is_new_visit',
'is_well_known_bot',
'visit_interval',
'is_entrance',
'is_exit',
'conversion_page',
'subtotal',
'item_code',
'enter_at',
'entrance_site',
'entrance_page_path',
'entrance_query_param',
'entrance_referring_page',
'entrance_referring_page_path',
'site_enter_to_cv'], axis='columns')
# 厳密に列と型を合わせる必要があるため注意すること
merge_df = pd.concat([ac_df, cv_df])
merge_df = merge_df.sort_values(['session_id', 'date'], ascending=[True, True])
cv_df_session_id = cv_df[["session_id"]].drop_duplicates()
merge_df_cv = pd.merge(cv_df_session_id, merge_df, on='session_id', how='inner')
# 各購入につき、サイト遷移している数を調べる
result = []
for session_id, group in merge_df_cv.groupby('session_id'):
conversion_indices = group[group['data_type'] == 'conversion'].index
# 各 'conversion' の行が最後になるwindow処理
start_idx = 0
for conv_idx in conversion_indices:
# 該当の 'conversion' 行までのデータを抽出
window = group.loc[start_idx:conv_idx]
# conversion行のdateを取得
conversion_date = group.loc[conv_idx, 'date']
# windowのサイズ(行数)を計算(-1の理由はconversionのタイミングにも同時にaccess_logがあるため。つまり、conversionしたタイミングのaccess_logが存在する)
window_size = len(window) -1
result.append([session_id, conversion_date, window_size])
# 次のウィンドウの開始位置を更新
start_idx = conv_idx + 1
cv_window_size_result_df = pd.DataFrame(result, columns=['session_id', 'date', 'num_pages_to_conversion'])
cv_df = pd.merge(cv_df, cv_window_size_result_df, on=['session_id','date'], how='inner')
grouped = cv_df.groupby('user_id')
df_site_enter_to_cv = grouped["site_enter_to_cv"].agg(['mean', 'min',"max"])
df_site_enter_to_cv = df_site_enter_to_cv.add_prefix('site_enter_to_cv_')
df_num_pages_to_conversion = grouped["num_pages_to_conversion"].agg(['mean', 'min',"max"])
df_num_pages_to_conversion = df_num_pages_to_conversion.add_prefix('num_pages_to_conversion_')
df_purchase_count = grouped["num_pages_to_conversion"].agg(["count"])
df_integrated = pd.merge(df_purchase_count, df_site_enter_to_cv, on='user_id', how='inner')
df_integrated = pd.merge(df_integrated, df_num_pages_to_conversion, on='user_id', how='inner')
df_integrated = df_integrated.reset_index()
return df_integrated
プロセスで出力したデータをそのまま Auto Model の元データとして利用することが可能です。今回は購入回数を数えている count 列を目的変数とします。
購買回数の分布はかなり極端です。
説明変数は特に配慮せず全てを選択しておきます。
分析モデルも特に考えず全てを選択しました。目的変数の自動選択は列数が少ないため採用しておりません。
決定木の精度が良いようですので詳細を確認します。
サイト遷移後購入までの滞在時間の最大値 「site_enter_to_cv_max」の重要度が高いようです。
今回は説明変数を2つ新たに作成してユーザーごとに集計したデータを用いましたが、もう少しユーザーをカテゴライズしてその傾向を見ると示唆が発見できそうです。下記のような分析を思いつきました。
- もう少し長い期間のデータを用いて、ユーザーの登録日からの日数でユーザーをカテゴリー化する。
- 購買ごとに登録後どのくらい期間が経ったユーザーの購入なのかを分析軸とする。
- 商品のマスターを参照することで、購入している商品をカテゴリー化する。
- ユーザーごとの「訪問頻度 / 登録日からの合計日数」を説明変数に追加する
今回は2つの分析例を取り上げましたが、AIStudio を用いることでデータの下処理と統計・機械学習モデリングが可能です。今回はモデル作成のための試行錯誤の一部をお見せましたが、出来の良いモデルが完成すればそれをもとにシミュレータを作成したり継続的に予測を行うことも可能です。
Rtoaster action+、insight+の分析環境として AIStudio を是非ご活用ください。
コメント
0件のコメント
記事コメントは受け付けていません。