16.4 生存分析¶
图书馆想知道会员通常能坚持借阅多久。小率翻到研究截止日,发现有些会员已经停止借阅,有些人仍在活跃。均哥说:“这些还没流失的人不能丢掉,也不能当作已经流失。它们叫删失。”
生存分析(Survival Analysis)研究“事件何时发生”。事件可以是患者复发、机器故障、用户流失,也可以是会员停止借阅。
16.4.1 删失让普通平均值不够用¶
每个观察对象有两个核心量:
- 时间 \(T\):从起点到事件或观察结束的时间。
- 状态 \(\delta\):事件是否已经发生,发生为 1,删失为 0。
| 会员 | 观察时间(月) | 是否流失 |
|---|---|---|
| A | 8 | 1 |
| B | 12 | 0 |
| C | 5 | 1 |
| D | 15 | 0 |
如果把删失的 12 和 15 当作真实流失时间,会低估留存;如果直接删除,又会浪费信息。
16.4.2 生存函数描述仍然活跃的概率¶
生存函数(Survival Function)定义为:
\[
S(t)=P(T>t)
\]
Kaplan-Meier 估计把每个发生事件的时间点串起来:
\[
\hat{S}(t)=\prod_{t_i\le t}\left(1-\frac{d_i}{n_i}\right)
\]
其中 \(d_i\) 是时间 \(t_i\) 的事件数,\(n_i\) 是那一刻仍在风险集中的人数。
16.4.3 风险函数看的是下一瞬间的危险¶
生存函数问“到 \(t\) 时还没有发生事件的概率”。风险函数(Hazard Function)问的是:
已经活到 \(t\) 的对象,在接下来很短时间内发生事件的倾向有多大?
可以写成:
\[
h(t)=\lim_{\Delta t\to 0}
\frac{P(t\le T<t+\Delta t\mid T\ge t)}{\Delta t}
\]
在用户留存里,风险高意味着“已经留到现在的用户,下一段时间更容易流失”。这比只看平均留存天数更细。
16.4.4 Cox 模型比较不同人群的风险¶
Cox 比例风险模型(Cox Proportional Hazards Model)常写作:
\[
h(t\mid \mathbf{x})=h_0(t)\exp(\beta_1x_1+\cdots+\beta_px_p)
\]
如果某个变量的风险比(Hazard Ratio, HR)为 1.5,意思是:在比例风险假设下,该变量增加对应的风险约为原来的 1.5 倍。HR 小于 1 则表示风险降低。
比例风险假设要检查
Cox 模型假设两组风险比随时间大致恒定。如果早期差异大、后期差异小,或者风险曲线交叉,就要考虑分层、时间交互或其他生存模型。
16.4.5 用 Python 画一条留存曲线¶
import numpy as np
import matplotlib.pyplot as plt
time = np.array([3, 5, 6, 8, 10, 12])
event = np.array([1, 1, 0, 1, 0, 1])
survival = []
s = 1.0
for t in sorted(set(time[event == 1])):
at_risk = np.sum(time >= t)
events = np.sum((time == t) & (event == 1))
s *= 1 - events / at_risk
survival.append((t, s))
xs, ys = zip(*survival)
plt.step([0, *xs], [1, *ys], where="post")
plt.ylim(0, 1.05)
plt.xlabel("months")
plt.ylabel("S(t)")
plt.show()
小率的笔记本
生存分析不只关心“是否发生”,更关心“什么时候发生”。删失不是缺失值,而是仍有用的不完整观察。Kaplan-Meier 曲线是理解留存和风险的第一张图。

