900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > python cox模型_python Cox比例风险假设检验-基于lifelines库

python cox模型_python Cox比例风险假设检验-基于lifelines库

时间:2019-07-18 17:27:39

相关推荐

python cox模型_python  Cox比例风险假设检验-基于lifelines库

在进行Cox之前需要对数据进行假设检验,查看数据是否符合比例风险不变的前提

以下内容皆来自lifelines官网,https://lifelines.readthedocs.io/en/latest/

目的:检验数据集是否服从比例不变的假设?

注意:

在进行之前,应仔思考,是否需要进行比例风险假设?

不这样做的原因有很多:

1、如果您的目标是生存预测,那么您就不必关心比例风险。您的目标是最大化一些分数,与预测的生成方式无关。

2、如果样本量非常大,会出现较小的违反 比例假设的情况,没关系的

3、有合理的理由假设所有数据集都会违反比例风险假设。Stensrud&Hernán的“为什么要对比例危害进行测试?”中对此进行了详细说明

from lifelines.datasets import load_rossi

from lifelines import CoxPHFitter

rossi_dataset = load_rossi() #使用自带的数据

cph = CoxPHFitter() #建立比例风险Cox模型

cph.fit(rossi_dataset, duration_col='week', event_col='arrest') #模型拟合

cph.check_assumptions(rossi_dataset, p_value_threshold=0.05, show_plots=True) #进行假设检验

可以看到age ,wexp这两个变量不符合假设

由于wexp是二分类变量,我们可以通过 strata 的方式,将其分层,再计算cph.fit(rossi_dataset, 'week', 'arrest', strata=['wexp'])

cph.print_summary(model="wexp in strata")

cph.check_assumptions(rossi_dataset, show_plots=True) #进行检验

可以看到wexp已经没有影响了,但age仍然违反比例风险假设,因此我们需要对age进行修改,使其符合比例风险模型的假设,有三种方法:

1、修改函数形式

如果协变量和对数风险之间的关联是非线性的,但模型仅进行线性拟合,可能会出现假阳性

因此,将变量变成非线性形式,看看是否符合,可以尝试选择添加二次项、三次项from lifelines.datasets import load_rossi

rossi_higher_order_age = rossi_dataset.copy()

rossi_higher_order_age['age'] = rossi_higher_order_age['age'] - rossi_higher_order_age['age'].mean()

rossi_higher_order_age['age**2'] = (rossi_higher_order_age['age'] - rossi_higher_order_age['age'].mean())**2

rossi_higher_order_age['age**3'] = (rossi_higher_order_age['age'] - rossi_higher_order_age['age'].mean())**3

cph.fit(rossi_higher_order_age, 'week', 'arrest', strata=['wexp'])

cph.print_summary(model="quad and cubic age terms"); print()

cph.check_assumptions(rossi_higher_order_age, show_plots=True, p_value_threshold=0.05)

可以看到,二项式或三项式符合模型的假设

2、对变量进行分层

将变量为大小相等的分类

如果分层过大,缺点是丢失大多数信息(因为将不同的值合并在一类)

因此,最佳分层数值介于两者之间from lifelines.datasets import load_rossi

import pandas as pd

rossi_strata_age = rossi_dataset.copy()

rossi_strata_age['age_strata'] = pd.cut(rossi_strata_age['age'], np.arange(0, 80, 3))

#生成一个0-80,间隔为3的队列,把年龄按照其所处的位置进行划分

rossi_strata_age[['age', 'age_strata']].head()

# 删除原始的age的列

rossi_strata_age = rossi_strata_age.drop('age', axis=1)

cph.fit(rossi_strata_age, 'week', 'arrest', strata=['age_strata', 'wexp'])

cph.print_summary(3, model="stratified age and wexp")

cph.check_assumptions(rossi_strata_age)

提示现在数据符合比例风险模型的假设

3、引入随时间变化的协变量

分两个步骤完成:

第一步,是将数据集转换为episodic格式。这意味着我们将变量从单行拆分为n新行,每个新行代表该变量的某个时间段。from lifelines.utils import to_episodic_format

rossi_dataset = load_rossi() #导入数据

rossi_long = to_episodic_format(rossi_dataset, duration_col='week', event_col='arrest', time_gaps=1.)

#转化数据格式,time_gap参数指定周期大小

rossi_dataset.head(25)

rossi_long.head(25)

发现每个样本都多了一个新的ID列(可以在数据框中自己指定该ID)。

该ID用于跟踪一段时间内的样本。请注意,arrest在(可能)事件发生之前的所有期间,col均为0

第二步,是在age和stop之间创建一个交互项。这是随时间变化的变量。

因为我们正在处理episodic格式。必须使用CoxTimeVaryingFitter代替CoxPHFitter,rossi_long['time*age'] = rossi_long['age'] * rossi_long['stop']

from lifelines import CoxTimeVaryingFitter

ctv = CoxTimeVaryingFitter()

ctv.fit(rossi_long,

id_col='id',

event_col='arrest',

start_col='start',

stop_col='stop',

strata=['wexp'])

ctv.print_summary(3, model="age * time interaction")

ctv.plot()

结论:

使用3种方法中,任何一种方法,点估计和标准误差都非常接近,因此使用任何一种方法都可以

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。