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种方法中,任何一种方法,点估计和标准误差都非常接近,因此使用任何一种方法都可以

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351