name: 同期群分析 description: 跟踪和分析用户同期群随时间的变化,计算留存率,并识别客户生命周期和留存分析中的行为模式
同期群分析
概览
同期群分析跟踪具有共同特征的用户群体随时间的变化,揭示留存、参与度和终身价值的模式。
何时使用
- 测量用户留存率并识别何时用户流失
- 分析客户终身价值(LTV)和回报期
- 比较不同用户获取渠道或活动的表现
- 了解产品变化如何随时间影响不同用户群体
- 跟踪参与模式并识别流失的早期预警信号
- 评估改进用户引导或功能发布对长期影响
核心概念
- 同期群: 共享特征的用户群体(注册日期、地区等)
- 同期群大小: 初始群体大小
- 留存率: 剩余活跃的百分比
- 流失率: 离开的百分比
- 留存曲线: 同期群随时间的降解情况
同期群类型
- 获取日期: 按注册周期分组的用户
- 行为: 按采取的行动分组的用户
- 收入: 按购买价值分组的用户
- 地理: 按位置分组的用户
- 人口统计: 按特征分组的用户
使用Python实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 创建样本用户生命周期数据
np.random.seed(42)
# 生成用户数据
n_users = 5000
users = []
for user_id in range(n_users):
signup_month = np.random.choice(range(1, 13))
lifetime_months = np.random.poisson(6) + 1
for month in range(1, lifetime_months + 1):
users.append({
'user_id': user_id,
'signup_month': signup_month,
'month': month,
'active': 1,
})
df = pd.DataFrame(users)
# 添加派生列
df['cohort_month'] = df['signup_month']
df['cohort_age'] = df['month'] # 可以是天、周等。
df['date'] = pd.to_datetime('2023-01-01') + pd.to_timedelta(df['signup_month'] * 30, unit='D')
print("用户数据摘要:")
print(df.head(10))
# 1. 同期群表(留存矩阵)
cohort_data = df.groupby(['cohort_month', 'cohort_age']).agg({
'user_id': 'nunique'
}).reset_index()
cohort_data.columns = ['cohort_month', 'cohort_age', 'unique_users']
# 创建透视表
cohort_pivot = cohort_data.pivot(index='cohort_month', columns='cohort_age', values='unique_users')
print("
同期群大小(原始用户计数):")
print(cohort_pivot)
# 2. 同期群留存(作为同期群大小的百分比)
cohort_size = cohort_pivot.iloc[:, 0]
retention_table = cohort_pivot.divide(cohort_size, axis=0) * 100
print("
同期群留存率(%):")
print(retention_table.round(1))
# 3. 可视化留存矩阵
fig, axes = plt.subplots(2, 1, figsize=(14, 8))
# 原始计数的热图
sns.heatmap(cohort_pivot, annot=True, fmt='g', cmap='YlOrRd', ax=axes[0],
cbar_kws={'label': '用户计数'})
axes[0].set_title('同期群大小 - 用户计数')
axes[0].set_xlabel('同期群年龄(月)')
axes[0].set_ylabel('同期群月份')
# 留存率的热图
sns.heatmap(retention_table, annot=True, fmt='.0f', cmap='RdYlGn', vmin=0, vmax=100,
ax=axes[1], cbar_kws={'label': '留存%'})
axes[1].set_title('同期群留存率(%)')
axes[1].set_xlabel('同期群年龄(月)')
axes[1].set_ylabel('同期群月份')
plt.tight_layout()
plt.show()
# 4. 留存曲线
fig, ax = plt.subplots(figsize=(12, 6))
# 为每个同期群绘制留存曲线
for cohort_month in cohort_pivot.index[:8]: # 前8个同期群
cohort_retention = retention_table.loc[cohort_month]
ax.plot(cohort_retention.index, cohort_retention.values, marker='o', label=f'同期群 {cohort_month}')
ax.set_xlabel('同期群年龄(月)')
ax.set_ylabel('留存率(%)')
ax.set_title('按同期群的留存曲线')
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
ax.grid(True, alpha=0.3)
ax.set_ylim([0, 105])
plt.tight_layout()
plt.show()
# 5. 平均留存曲线
fig, ax = plt.subplots(figsize=(10, 6))
# 计算每个年龄的平均留存
avg_retention = retention_table.mean()
ax.plot(avg_retention.index, avg_retention.values, marker='o', linewidth=2, markersize=8, color='navy')
ax.fill_between(avg_retention.index, avg_retention.values, alpha=0.3, color='navy')
# 添加置信区间
std_retention = retention_table.std()
ax.fill_between(std_retention.index,
avg_retention - std_retention,
avg_retention + std_retention,
alpha=0.2, color='navy', label='±1 标准差')
ax.set_xlabel('同期群年龄(月)')
ax.set_ylabel('留存率(%)')
ax.set_title('平均留存曲线与置信带')
ax.legend()
ax.grid(True, alpha=0.3)
ax.set_ylim([0, 105])
plt.tight_layout()
plt.show()
# 6. 流失率
churn_rate = 100 - retention_table
print("
流失率(%):")
print(churn_rate.round(1).head())
# 7. 收入同期群分析
# 添加收入数据
np.random.seed(42)
df['revenue'] = np.random.exponential(50, len(df))
# 按同期群的收入
revenue_data = df.groupby(['cohort_month', 'cohort_age']).agg({
'revenue': 'sum',
'user_id': 'nunique'
}).reset_index()
revenue_data['revenue_per_user'] = revenue_data['revenue'] / revenue_data['user_id']
revenue_pivot = revenue_data.pivot(index='cohort_month', columns='cohort_age', values='revenue')
rpu_pivot = revenue_data.pivot(index='cohort_month', columns='cohort_age', values='revenue_per_user')
# 可视化收入
fig, axes = plt.subplots(2, 1, figsize=(14, 8))
sns.heatmap(revenue_pivot, annot=True, fmt='.0f', cmap='YlGnBu', ax=axes[0],
cbar_kws={'label': '总收入($)'})
axes[0].set_title('按同期群的总收入')
axes[0].set_xlabel('同期群年龄(月)')
axes[0].set_ylabel('同期群月份')
sns.heatmap(rpu_pivot, annot=True, fmt='.2f', cmap='YlGnBu', ax=axes[1],
cbar_kws={'label': '每位用户的收入($)'})
axes[1].set_title('按同期群的每位用户收入')
axes[1].set_xlabel('同期群年龄(月)')
axes[1].set_ylabel('同期群月份')
plt.tight_layout()
plt.show()
# 8. 终身价值计算
df['month_since_signup'] = df['cohort_age']
ltv_data = df.groupby('user_id').agg({
'revenue': 'sum',
'cohort_month': 'first',
'month_since_signup': 'max',
}).reset_index()
ltv_data.columns = ['user_id', 'lifetime_value', 'cohort_month', 'lifetime_months']
# 按同期群的平均LTV
ltv_by_cohort = ltv_data.groupby('cohort_month')['lifetime_value'].agg(['mean', 'median', 'std'])
print("
同期群的终身价值:")
print(ltv_by_cohort.round(2))
fig, ax = plt.subplots(figsize=(10, 6))
ltv_by_cohort['mean'].plot(kind='bar', ax=ax, color='skyblue', edgecolor='black')
ax.set_title('按同期群的平均终身价值')
ax.set_xlabel('同期群月份')
ax.set_ylabel('终身价值($)')
ax.grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()
# 9. 同期群随时间的构成
fig, ax = plt.subplots(figsize=(12, 6))
# 按同期群每月活跃用户
active_by_month = df.groupby(['date', 'cohort_month']).size().reset_index(name='active_users')
pivot_active = active_by_month.pivot(index='date', columns='cohort_month', values='active_users')
pivot_active.plot(ax=ax, marker='o')
ax.set_title('按同期群每月活跃用户')
ax.set_xlabel('月份')
ax.set_ylabel('活跃用户')
ax.legend(title='同期群月份', bbox_to_anchor=(1.05, 1))
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 10. 同期群摘要指标
summary_metrics = pd.DataFrame({
'同期群月份': cohort_size.index,
'初始规模': cohort_size.values,
'第1个月留存': retention_table.iloc[:, 0].values,
'第3个月留存': retention_table.iloc[:, min(2, retention_table.shape[1]-1)].values,
'平均LTV': ltv_by_cohort['mean'].values,
})
print("
同期群摘要指标:")
print(summary_metrics.round(2))
# 11. 可视化比较
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
# 第1个月与第3个月留存
ax_plot = axes[0]
months = ['第1个月', '第3个月']
month_1_ret = retention_table.iloc[:, 0].mean()
month_3_ret = retention_table.iloc[:, min(2, retention_table.shape[1]-1)].mean()
ax_plot.bar(months, [month_1_ret, month_3_ret], color=['#1f77b4', '#ff7f0e'], edgecolor='black')
ax_plot.set_ylabel('留存率(%)')
ax_plot.set_title('按里程碑的平均留存')
ax_plot.set_ylim([0, 100])
for i, v in enumerate([month_1_ret, month_3_ret]):
ax_plot.text(i, v + 2, f'{v:.1f}%', ha='center')
# 同期群规模趋势
axes[1].plot(cohort_size.index, cohort_size.values, marker='o', linewidth=2, markersize=8)
axes[1].set_xlabel('同期群月份')
axes[1].set_ylabel('同期群规模')
axes[1].set_title('随时间变化的同期群规模')
axes[1].grid(True, alpha=0.3)
# LTV趋势
axes[2].plot(ltv_by_cohort.index, ltv_by_cohort['mean'].values, marker='o', linewidth=2, markersize=8, color='green')
axes[2].set_xlabel('同期群月份')
axes[2].set_ylabel('平均终身价值($)')
axes[2].set_title('按同期群的LTV趋势')
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print("
同期群分析完成!")
关键指标
- 留存率: 同期群活跃的百分比
- 流失率: 同期群流失的百分比
- 第1天/月留存: 早期参与度
- 终身价值: 每位用户的总收入
- 回报期: 回收CAC的时间
寻找的洞察
- 早期留存预测器
- 同期群之间的差异
- 季节性模式
- 参与度下降
- 收入趋势
交付物
- 同期群留存矩阵
- 留存曲线可视化
- 流失率分析
- 终身价值计算
- 每个同期群的收入
- 带有洞察的执行摘要
- 可操作的建议