生存分析
生存分析主要用于医学研究,比如医疗方案对病人寿命的影响。后面用来探究所感兴趣的事件的发生的时间的统计方法。比如产品的寿命分析、工程中的失败时间分析等等。这里病人死亡、产品淘汰和工程失败等称为事件event。生存分析中有两个重要的概念,一是生存函数,二是风险函数。
生存函数的形式如下,表示为事件未发生的样本比例随时间变化的趋势,比如存活病人样本比例、可正常使用产品比例随时间的变化趋势等。
风险函数的形式如下,表示为事件发生概率的变化率。
两个函数之间的关系如下。
用户分析
用户行为分析,特别是Customer Lifetime Value,对用户运营和用户增长工作尤为重要。了解用户在特定时间的行为程度更能帮助运营人员开展运营活动,提高用户价值。而常用的AB testing方法无法进行跨产品平台的定量分析,回归模型无法动态测量用户随时间变化的行为程度概率。因此借助生存分析可以进行用户留存、用户点击、用户购买等行为随时间变化的趋势。
比如以用户购买行为为例,一般的运营数据,直接进行用户分层查看其转化率,但是这样的数据无法知道用户的动态行为,比如在哪个时间点用户转化率会发生突变,产品的转化率会稳定在多少。生存分析以一个用户的单位,以用户注册时间为实验开始,数据采集截止时间(右删失)或用户转化时间为实验终止,用户最后是否发生购买行为为事件。
实例
数据集:2020年1月1日-2020年1月10日间注册的用户
user_id:用户id
register_date:注册时间
gender:性别
have_bought:是否购买(1为是,0为否)
duration:间隔时间
buy_time:购买时间
# 导入需要的包
from lifelines import NelsonAalenFitter, CoxPHFitter, KaplanMeierFitter
import pandas as pd
from matplotlib.pyplot import *
import matplotlib.pyplot as plt
# 读取数据集
df = pd.read_excel('survival.xlsx')
# 生存函数:事件未发生的样本比例随时间变化的趋势
kmf = KaplanMeierFitter()
kmf.fit(df['duration'], event_observed=df['have_bought'], label='all')
kmf.plot()
plt.show()
转化率随时间的变化如下,发现在20天左右转化率基本稳定在90%,即在注册后的20天内大概有90%的用户有购买行为。如果运营能在该时间点开展营销活动,会促进注册会员的转化。
当然,也可以更加细分,看不同性别下的转化率与时间的关系。
ax = subplot(111)
t = np.linspace(0, 50, 51)
kmf.fit(df[df['gender'] == 'male']['duration'], event_observed=df[df['gender'] == 'male']['have_bought'], timeline=t, label="male")
ax = kmf.plot(ax=ax)
kmf.fit(df[df['gender'] == 'female']['duration'], event_observed=df[df['gender'] == 'female']['have_bought'], timeline=t, label="female")
ax = kmf.plot(ax=ax)
plt.ylim(0,1)
plt.title("not buying rate between two gender")
plt.show()
# 风险函数:事件发生概率的变化率
naf = NelsonAalenFitter()
naf.fit(df['duration'], event_observed=df['have_bought'], timeline=t, label='all')
naf.plot_hazard(bandwidth=20)
plt.show()
转化率随时间变化的变化速率如下,转化率在前5天缓慢增加,之后开始下降,且10-20天之间下降速度很快,如果运营能在购买意愿下降前采取措施将有利于用户的转化。
同样,也可以更加细分,看不同性别下的转化率的变化速率与时间的关系。
ax = subplot(111)
t = np.linspace(0, 50, 51)
naf.fit(df[df['gender'] == 'female']['duration'], event_observed=df[df['gender'] == 'female']['have_bought'], timeline=t, label="female")
ax = naf.plot_hazard(bandwidth=20, ax=ax)
naf.fit(df[df['gender'] == 'male']['duration'], event_observed=df[df['gender'] == 'male']['have_bought'], timeline=t, label="male")
ax = naf.plot_hazard(bandwidth=20, ax=ax)
plt.title("hazard function (convertion diff rate) between two gender")
plt.show()