Pandas ユーザー行動分析実践

ユーザー行動分析はプロダクト最適化の重要な根拠です。本ケースでは、ユーザーの訪問、リテンション、コンバージョンなどの行動データを分析する方法を紹介します。


データ準備

ユーザー行動データのシミュレーション

例

import pandas as pd
import numpy as np

np.random.seed(42)
n_users = 500
n_events = 5000

# ユーザー基本情報
users = pd.DataFrame({
    "ユーザーID": range(1, n_users + 1),
    "登録日": pd.date_range("2024-01-01", periods=n_users, freq="D")[:n_users],
    "チャネル": np.random.choice(["自然検索", "広告", "レコメンド", "ソーシャル"], n_users),
    "デバイス": np.random.choice(["PC", "Mobile", "Tablet"], n_users, p=[0.3, 0.6, 0.1])
})

# ユーザー行動イベント
events = pd.DataFrame({
    "イベントID": range(1, n_events + 1),
    "ユーザーID": np.random.randint(1, n_users + 1, n_events),
    "イベントタイプ": np.random.choice(
        ["閲覧", "クリック", "お気に入り", "カート追加", "注文", "コメント"],
        n_events,
        p=[0.4, 0.25, 0.1, 0.1, 0.1, 0.05]
    ),
    "イベント時間": pd.date_range("2024-01-15", periods=n_events, freq="10min")
})

# データ結合
events = events.merge(users[["ユーザーID", "チャネル", "デバイス"]], on="ユーザーID")

print("ユーザーデータ:")
print(users.head())
print(f"\nユーザー数: {len(users)}")
print("\nイベントデータ:")
print(events.head())
print(f"\nイベント数: {len(events)}")

ユーザーアクティブ分析

イベントタイプ分布

例

# イベントタイプ集計
event_dist = events["イベントタイプ"].value_counts()
event_pct = events["イベントタイプ"].value_counts(normalize=True) * 100

print("=== イベントタイプ分布 ===\n")
event_analysis = pd.DataFrame({
    "回数": event_dist,
    "割合": event_pct.round(2)
})
print(event_analysis)
print()

# 各イベントタイプのユーザー数
event_users = events.groupby("イベントタイプ")["ユーザーID"].nunique()
print("各イベントタイプの参加ユーザー数:")
print(event_users)

ユーザーエンゲージメント

例

# ユーザーイベント集計
user_events = events.groupby("ユーザーID").agg({
    "イベントID": "count",
    "イベントタイプ": lambda x: x.nunique()
}).rename(columns={
    "イベントID": "イベント総数",
    "イベントタイプ": "イベントタイプ数"
})

print("=== ユーザーエンゲージメント ===\n")
print(f"ユーザー1人あたりの平均イベント数: {user_events['イベント総数'].mean():.1f}")
print(f"中央値: {user_events['イベント総数'].median():.0f}")
print(f"最大: {user_events['イベント総数'].max()}")
print()

# ユーザーセグメント化
user_events["アクティブ度"] = pd.cut(
    user_events["イベント総数"],
    bins=[0, 3, 10, 20, float("inf")],
    labels=["低アクティブ", "普通", "アクティブ", "高アクティブ"]
)

print("ユーザーアクティブ度分布:")
print(user_events["アクティブ度"].value_counts())

コンバージョンファネル分析

コンバージョンパス

例

# イベントタイプごとのユーザー数を計算
funnel = events.groupby("イベントタイプ")["ユーザーID"].nunique()
funnel = funnel.reindex(["閲覧", "クリック", "お気に入り", "カート追加", "注文", "コメント"])

# コンバージョン率を計算
funnel_df = pd.DataFrame({
    "ユーザー数": funnel,
    "絶対コンバージョン率": (funnel / funnel["閲覧"] * 100).round(2),
    "ステップコンバージョン率": (funnel / funnel.shift(1) * 100).round(2)
}).fillna(100)

print("=== コンバージョンファネル ===\n")
print(funnel_df)
print()

# ファネルデータを可視化
print("ファネルデータ:")
for step, row in funnel_df.iterrows():
    print(f"{step}: {row['ユーザー数']} 人 ({row['絶対コンバージョン率']:.1f}%)")

チャネル分析

各チャネルのパフォーマンス

例

# チャネル別ユーザー分析
channel_analysis = events.groupby("チャネル").agg({
    "ユーザーID": "nunique",
    "イベントID": "count"
}).rename(columns={
    "ユーザーID": "ユーザー数",
    "イベントID": "イベント数"
})

channel_analysis["ユーザー1人あたりのイベント数"] = (
    channel_analysis["イベント数"] / channel_analysis["ユーザー数"]
).round(2)

print("=== チャネル分析 ===\n")
print(channel_analysis)
print()

# チャネル別コンバージョン比較
channel_funnel = events[events["イベントタイプ"].isin(["閲覧", "注文"])].groupby(
    ["チャネル", "イベントタイプ"]
)["ユーザーID"].nunique().unstack()

channel_funnel["コンバージョン率"] = (
    channel_funnel["注文"] / channel_funnel["閲覧"] * 100
).round(2)

print("各チャネルのコンバージョン率:")
print(channel_funnel)

デバイス分析

例

# デバイス分析
device_analysis = events.groupby("デバイス").agg({
    "ユーザーID": "nunique",
    "イベントID": "count"
}).rename(columns={
    "ユーザーID": "ユーザー数",
    "イベントID": "イベント数"
})

device_analysis["ユーザー1人あたりのイベント数"] = (
    device_analysis["イベント数"] / device_analysis["ユーザー数"]
).round(2)

print("=== デバイス分布 ===\n")
print(device_analysis)
print()

# デバイス別コンバージョン率
device_funnel = events[events["イベントタイプ"].isin(["閲覧", "注文"])].groupby(
    ["デバイス", "イベントタイプ"]
)["ユーザーID"].nunique().unstack()

device_funnel["コンバージョン率"] = (
    device_funnel["注文"] / device_funnel["閲覧"] * 100
).round(2)

print("各デバイスのコンバージョン率:")
print(device_funnel)

リテンション分析

例

# 簡易リテンション分析
# 登録後7日以内にアクティブであればリテンションとみなす
users_with_events = events.groupby("ユーザーID")["イベント時間"].agg(["min", "max"])
users_with_events.columns = ["初回アクティブ日", "最終アクティブ日"]

# 登録情報を結合
users_analysis = users.merge(users_with_events, left_on="ユーザーID", right_index=True, how="left")

# アクティブ日数を計算
users_analysis["アクティブ日数"] = (
    users_analysis["最終アクティブ日"] - users_analysis["初回アクティブ日"]
).dt.days + 1

print("=== ユーザーリテンション分析 ===\n")
print(f"行動ありユーザー: {len(users_with_events)}")
print(f"平均アクティブ日数: {users_analysis['アクティブ日数'].mean():.1f} 日")
print()

# 翌日リテンション(簡易)
retention_1d = len(users_analysis[users_analysis["アクティブ日数"] >= 2]) / len(users_analysis) * 100
retention_3d = len(users_analysis[users_analysis["アクティブ日数"] >= 3]) / len(users_analysis) * 100

print(f"翌日リテンション率: {retention_1d:.1f}%")
print(f"3日リテンション率: {retention_3d:.1f}%")

分析まとめ

例

print("""
=== ユーザー行動分析まとめ ===

1. ユーザーエンゲージメント
- イベントタイプは閲覧が中心で、次いでクリックが多い
- ユーザー1人あたりの平均イベント数が少なく、ユーザーの粘着性を高める必要がある

2. コンバージョンファネル
- 離脱が大きく、ユーザー体験の最適化が必要
- 閲覧から注文までのコンバージョン率が低い

3. チャネル効果
- ユーザー数が多いチャネルのコンバージョンパスを重点的に最適化することを推奨
- チャネルごとにパフォーマンス差があるため、きめ細かな運用が必要

4. デバイスのパフォーマンス
- Mobile が主要デバイスであり、モバイル体験の最適化に重点的に取り組む必要がある

5. 最適化の提案
- 1) 商品表示を最適化し、閲覧→クリックのコンバージョンを向上させる
- 2) 購入フローを簡素化し、注文時の離脱を減らす
- 3) Mobile向けにページの読み込み速度を最適化する
- 4) ユーザーセグメントに基づく運用体制を構築する
"""
)
その他の拡張機能