Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分

4. 时间依存系数

时间依存协变量(covariates)和时间依存系数(coefficients)是两种不同的扩展Cox模型,如下面的两个等式所示。
λ ( t ) = λ 0 ( t ) e β X ( t ) \lambda(t)=\lambda_0(t) e^{\beta X(t)} λ(t)=λ0(t)eβX(t) (1)
λ ( t ) = λ 0 ( t ) e β ( t ) X \lambda(t)=\lambda_0(t) e^{\beta (t)X} λ(t)=λ0(t)eβ(t)X (2)

等式(1)是时间依存协变量,是一种常用且易于理解的用法。 等式(2)具有时间相关系数,这种模型不太常见,但代表了一种处理非比例风险的方法。而通常比例风险假设恰恰是不随时间变化的系数: β ( t ) = c \beta (t)=c β(t)=ccox.zph函数将绘制研究的 β ( t ) \beta (t) β(t)的估计值,用于诊断和理解非比例危险。以下是一个使用退伍军人癌症数据veteran的测试案例。

library(survival)
options(show.signif.stars=FALSE)
vfit<-coxph(Surv(time,status)~trt+prior+karno, veteran)
vfit

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第1张图片

quantile(veteran$karno)

在这里插入图片描述

zp<-cox.zph(vfit, transform=function(time) log(time+20))
zp

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第2张图片

plot(zp[3])
abline(0,0, col=2)
abline(h=vfit$coef[3], col=3, lwd=2, lty=2)

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第3张图片
Karnofsky得分是一个非常重要的预测因子,但它的效果随着时间的推移并不是恒定的,如测试结果和绘图所示。 在早期它有一个很大的负面效果:在第一个四分位值的病人,风险大约是在第三个四分位数值的病人的exp(35 * .03377)=3.2倍;但到了200天,这种关系已经减少到并没有多少,和零差不多了。 一种解释是,在这种非常严重的疾病中,任何超过6个月之前的措施都不再适用。

比例风险模型估计的是随时间的平均危险,其值由虚线水平线表示。 使用平均危险通常是合理的,比例风险假设毕竟不是那么精确的。 然而,在这种情况下,与均线的背离是如此之大,这时依赖于时间的系数是对实际状态则是一种更有用的总结。 cox.zph图非常适合诊断,但不能产生一个合适的 β ( t ) \beta (t) β(t),那么我们如何来建立这个模型呢?

4.1 阶梯函数

一种最简单的扩展是 β ( t ) \beta (t) β(t)的阶梯函数,例如,不同时间间隔采用不同系数。一种简单的方法是使用survSplit函数将数据集分解为时间相关的部分。我们会将上述veteran数据任意划分为前3个月,3-6个月和6个月以上的3个时期。

vet2 <- survSplit(Surv(time, status) ~ ., data= veteran, cut=c(90, 180),
episode= "tgroup", id="id")
vet2[1:7, c("id", "tstart", "time", "status", "tgroup", "age", "karno")]

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第4张图片

vfit2 <- coxph(Surv(tstart, time, status) ~ trt + prior + karno:strata(tgroup), data=vet2)
vfit2

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第5张图片

cox.zph(vfit2)

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第6张图片
修正后的数据显示,基线Karnofsky评分的效果基本上限于前两个月。 cox.zph函数没有显示Karnofsky评分进一步的时间依赖效应了。 后面一点当然不足为奇,因为我们使用了原始图表来选择切割点。 三个区间的系数将会不同,会受到序列过程影响产生偏差,必须谨慎查看。
后期的生存曲线拟合则需要更多的关注。 默认曲线使用协变量的平均值,在这种情况下总会有问题且完全无用。 查看模型的均值如下:

vfit2$means

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第7张图片
默认曲线将针对治疗组1.47上的某人,这适用于任何人,以及Karnofsky评分的单组“混合”值,每次都是三个Karnofsky系数。 这个可以通过创建具有时间间隔的新数据集来进行纠正。 我们创建了两个标记为“曲线1”和“曲线2”的假设受试者。无论是在治疗1还是没有事先治疗的情况下,一个人的Karnofsky为40,另一个人为75。 每个都具有时间依赖性协变量tgroup的适当值,分别在0-90,90-180和180+天为1,2,3。 我们将绘制第一年的曲线。

cdata <- data.frame(tstart= rep(c(0,90,180), 2),
	time = rep(c(90,180, 365), 2),
	status= rep(0,6), #necessary, but ignored
	tgroup= rep(1:3, 2),
	trt = rep(1,6),
	prior= rep(0,6),
	karno= rep(c(40, 75), each=3),
	curve= rep(1:2, each=3))
cdata	

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第8张图片

sfit <- survfit(vfit2, newdata=cdata, id=curve)
km <- survfit(Surv(time, status) ~ I(karno>60), veteran)
plot(km, xmax= 365, col=1:2, lwd=2,xlab="Days from enrollment", ylab="Survival")
lines(sfit, col=1:2, lty=2, lwd=2)

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第9张图片
基于coxph模型的生存曲线的默认行为是为输入数据中的每一行创建一条曲线; id选项使它为每条曲线使用一组线。 在第25和第75百分位数处的Karnofsky值大致分别代表受试者的下半部分和上半部分的平均分数,并且在低于和高于中值的Kaplan-Meier曲线的顶部。

4.2 连续的时间依存系数

如果假定 β ( t ) \beta (t) β(t)具有简单的函数形式,我们可以欺骗一个普通的Cox模型程序来进行拟合。例如, β ( t ) \beta (t) β(t)= a + b log(t)是一种经常被假设的特定形式。然后 β ( t ) \beta (t) β(t)x = ax + b log(t)x = ax + bz,被用于特殊时间相关协变量z = log(t)x。 选择在log(t+20)之上用cox.zph图的时间尺度,使得该图的前200天大致呈线性。 根据这个简单的线性模型并不适合整个范围,但我们将继续前进并将其作为一个简单的例子。一个明显但不正确的方法是:

vfit3 <- coxph(Surv(time, status) ~ trt + prior + karno + 
		I(karno * log(time + 20)), data=veteran)

这实在是个常犯错误,以致于更新的coxph例程会输出这种尝试的错误提示信息。 这个错误的问题在于,上面的代码实际上并没有创建一个时间相关的协变量,而是根据协变量的时间为每个受试者创建一个时间静态值; 与我们在coxph调用之外构造变量没有什么不同。这个变量非常明确地打破了关于不能展望未来的规则,人们很快就会发现循环性:大的时间值似乎可以预测长期生存,因为长期生存导致了大量的时间价值。

一个正确的连续型时间依存协变量可以被time-transform函数构造,如下:

vfit3 <- coxph(Surv(time, status) ~ trt + prior + karno + tt(karno), 
		data=veteran,			
		tt = function(x, t, ...) x * log(t+20))
vfit3

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第10张图片

plot(zp[3])
abline(coef(vfit3)[3:4], col=2)

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第11张图片
时间相关系数估计为 β ( t ) \beta (t) β(t)= -0.125 + 0.021 * log(t + 20)。 我们可以将该拟合线添加到cox.zph图中。 毫不奇怪,结果对于时间> 200来说太高而且低估了初始斜率。 但是,这个拟合仍然优于vfit中的常数为水平线的拟合,正如vfit3中斜率项的p值所证实的那样。 (来自cox.zph的该项的p值几乎相同,正如它必须是几乎一致的,因为cox.zph中的测试是针对所选时间尺度上的线性效应。)

顺便提一下,这种相同的编码二分法同样存在于SAS phreg中。将时间添加到模型语句的右侧将创建时间固定变量(这是不正确的),而phreg中使用time作为变量的编程语句将生成时间相关对象。这种错误的可能性较小,因为phreg的模型语句比R更不灵活,也就是说,在SAS中你不能简单地在右侧写"log(time)"。

5.1 时间依存协变量

延续上章节 β ( t ) \beta (t) β(t)的例子,值得额外注意的是,使用编程语句来创建是/否变量可能会出现另一种常见的错误。 假设有一个数据集有两个时间变量:从登记到最后一次随访的时间(lfu)和到糖尿病发生的时间(diabetes);然后比如说,我们希望使用糖尿病的出现作为时间依存协变量。 以下是一个自建的小例子:

data1 <- read.table(col.names=c("id", "diabetes", "lfu", "status"),
	header=FALSE, text="
	1 5 30 1
	2 10 15 1
	3 NA 60 0
	4 NA 80 1
	5 10 80 0
	6 NA 90 1
	7 30 95 1
	")
data1$d2 <- pmin(data1$diabetes, 300, na.rm=TRUE) #replace NA with 300
fit1 <- coxph(Surv(lfu, status) ~ tt(d2), data=data1,
	tt = function(d2, t, ...) ifelse(t > d2, 1, 0))
fit2 <- coxph(Surv(lfu, status) ~ tt(d2), data=data1,
	tt = function(d2, t, ...) ifelse(t < d2, 0, 1))
c(coef(fit1), coef(fit2))

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第12张图片
在这里插入图片描述
人们可能期望拟合fit1和拟合fit2给出相同的系数,但从上述结果看,它们完全不同。 问题出在7号受试者,他的糖尿病发生时间正好落在一个事件发生时间内。 在fit1中,他们的糖尿病协变量在事件时间为30后有效地改变,在fit2中它在事件时间为30之前发生变化,因此第二个是不正确的。 举个例子说,比如赌博时,所有赌注必须放在轮盘球落地之前

当使用tmerge函数将数据集扩展为start, stop格式时,则将被正确处理。

data2 <- tmerge(data1, data1, id=id, dstat=event(lfu, status),
		diab = tdc(diabetes))
subset(data2, id %in% c(1,7), c(id, tstart:diab))
fit3 <- coxph(Surv(tstart, tstop, dstat) ~ diab, data2)
c(coef(fit1), coef(fit2), coef(fit3))

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第13张图片
在这里插入图片描述

5.2 可预测时间依存协变量

偶尔会有一个时间依存协变量,其未来的值是可预测的。其中最明显的是患者年龄,偶尔对于药物的累积剂量可能是正确的。 由于部分似然(partial likelihood)的结构,如果在模型中输入年龄作为线性项,那么在Cox模型将忽略年龄变化造成的效应。假设i号受试者在时间 t i t_i ti处具有一个事件;而其他受试者 j ∈ R i j\in R_i jRi在该时间处于一个累计年龄贡献的风险中。 那么其部分似然项定义为:
e β ∗ a i Σ j ∈ R i e β ∗ a j = e β ∗ ( a i + t i ) Σ j ∈ R i e β ∗ ( a j + t j ) \cfrac{e^{\beta*a_i}}{\Sigma_{j\in R_i} e^{\beta *a_j}}=\cfrac{e^{\beta*(a_i+t_i)}}{\Sigma_{j\in R_i} e^{\beta *(a_j+t_j)}} ΣjRieβajeβai=ΣjRieβ(aj+tj)eβ(ai+ti)

我们看到使用时间相关的年龄(等式右边)或基线时年龄(等式左边),其部分似然项是相同的,因为 e β t i e^{\beta t_i} eβti在分式中被取消了。 但是,如果年龄对风险的影响是非线性的,那么不能这样简单消去。

因为年龄是连续变化的,我们从理论上说需要一个非常大的数据集以捕捉这种效应,以每天为间隔直至死亡。但实际使用中并不需要这样做,因为尽管我们在变老,但是风险一般不会以天数为单位增加的那么快。

一种方法是使用coxph的time-transform创建时变协变量。 下面是使用pbc数据集的示例。 该数据集中最长的跟进时间超过13年,后续时间以天为单位,我们可能会担心中间数据集会很大。 然而,程序在事件发生时仅需要每个主题的时间相关协变量的值,因此中间数据集中的最大行数是受试者数量乘以事件次数。

pfit1 <- coxph(Surv(time, status==2) ~ log(bili) + ascites + age, pbc)
pfit2 <- coxph(Surv(time, status==2) ~ log(bili) + ascites + tt(age),
	data=pbc,
	tt=function(x, t, ...) {
	age <- x + t/365.25
	cbind(age=age, age2= (age-50)^2, age3= (age-50)^3)
	})
pfit2
anova(pfit2)

Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第14张图片
Cox模型中的时间依存协变量和时间依存系数(R语言)第二部分_第15张图片

2*(pfit2$loglik - pfit1$loglik)[2]			
#result: 10.80621

由于初始年龄是以年为单位而时间以天为单位,因此在tt函数内进行缩放非常重要。 在自由度为2时似然比为10.8,表明附加的定义比较显著。

如果在等式右侧有一个或多个项作为tt()运算操作符,则程序将为每个唯一的事件时间预先计算该变量的值。一个用户自定义函数的参数可以是:

  • 协变量:tt()调用内的任何内容
  • 事件时间
  • 事件编号:如果有多个层次并且在相同时间段内两个层级同时发生,则可以分别处理它们
  • 观察值的权重,如果调用函数使用了权重系数

底层代码单次调用函数,它使用一个巨大的x向量,包含的元素是每个受试者在每个事件时的风险。如果公式中有多个tt()项,则tt的参数应该是具有必需元素数的函数列表。然而需要注意的是,你不能将公式列为:log(bili)+ tt(age)+ tt(age)。原因是R公式解析器在结果未到达coxph函数之前即删除了冗余项。 (这对用户来说是一种很方便的操作,如y=x1 + x2 + x1不会在X矩阵中生成冗余列。)

适合上述模型的一种解决方法是直接创建扩展数据集,然后对扩展数据执行普通的coxph调用。当然,这样做的缺点是数据集非常大,但它不会大于tt调用后创建的内部数据集。优点是可以进一步处理模型,例如残差或生存曲线。以下例子重述了tt函数的调用。

dtimes <- sort(unique(with(pbc, time[status==2])))
tdata <- survSplit(Surv(time, status==2) ~., pbc, cut=dtimes)
tdata$c.age <- tdata$age + tdata$time/365.25 -50 #current age, centered at 50
pfit3 <- coxph(Surv(tstart, time, event) ~ log(bili) + ascites + c.age +
	I(c.age^2) + I(c.age^3), data=tdata)
rbind(coef(pfit2), coef(pfit3))

在这里插入图片描述
与起始pbc数据的418次观察相比,上述扩展产生了42401个观测值的数据集。 通常可以通过更粗略的时间网格获得合理的拟合:在pbc数据中,在第41天和第43天有一个事件,是否真的有必要在第二个中更新所有主题年龄2/365以反映增加风险? 因此替换为max(dtimes)/365.25 = 11.5年,将11年作为总跟进年数。

dtime2 <- 1:11 * 365.25
tdata2 <-survSplit(Surv(time, status==2) ~., pbc, cut=dtime2)
tdata2$c.age <- tdata2$age + tdata2$time/365.25 -50 #current age, centered at 50
pfit4 <- coxph(Surv(tstart, time, event) ~ log(bili) + ascites + c.age +
	I(c.age^2) + I(c.age^3), data=tdata2)
rbind('1 day grid'= coef(pfit3), '1 year grid'= coef(pfit4))
c(tdata=nrow(tdata), tdata2=nrow(tdata2))
#results:   tdata  42401; tdata2  2393

在这里插入图片描述可以看到在结果几乎相同的情况下,新数据集大小为原来的1/20。这使得大数据集的计算时间有很大差异。确切地说,如何“缩减”切割点主要基于对受试对象的特定认知,可以基于cox.zph图选择选定的点,或者从非常粗略的时间网格开始然后逐步精细计算。在这个数据集中,我们有理由说尽管风险随着年龄的增长而增加,但是年龄变化小于一年的影响其实很小。

Cox模型需要计算每个事件时间的协变量的加权平均值和方差,该过程本质上就是 O ( n d p 2 ) O(ndp^2) O(ndp2),其中n =样本大小,d =事件数量,p =协变量数量。底层代码中的大部分算法工作用于更新均值和方差矩阵,将计算时间减少到 O ( ( n + d ) p 2 ) O((n+d)p^2) O((n+d)p2)。在时间分割中不可能进行更新,并且计算重新开始,因为tt术语我们根本不会更新;甚至对于中等大小的数据集,nd与n + d对计算时间的影响都有可能是令人惊讶的。

tt函数还有其他有趣的用途。一个例子是O’Brien的logit-rank测试程序[6]。 他提议在每个事件时间用其队列排名的logit变换替换协变量。这消除了预测器x中任何异常值的影响。对于这种情况,我们忽略事件时间参数并专注于分组以创建以下tt函数。

function(x, t, riskset, weights){
	obrien <- function(x) {
		r <- rank(x)
		(r-.5)/(.5+length(r)-r)
	}
	unlist(tapply(x, riskset, obrien))
}

这依赖于tt()的输入参数按事件编号或风险集排序的事实。如果在coxph调用中不存在tt参数,则此函数用作默认值,但模型公式中有tt项。

另一个有趣的用法是用简单的等级替换数据,而不是重新调整为0~1。

function(x, t, riskset, weights)
	unlist(tapply(x, riskset, rank))

此模型的得分统计量为 ( C − D ) / 2 (C-D)/2 (CD)/2,其中C和D是一致配对和不一致配对的数量,请参阅survConcordance函数。 然后这种拟合的得分统计量是对于一致性统计的重要性测试,实际上是survConcordance报告的标准错误的基础。 O’Brien测试可以被视为一致性统计,其给予每个事件时间相同的权重,而标准的一致性将对每个事件与风险集的大小成比例地加权。

参考文献
[1] Anderson JR, Cain KC, and Gelber RD. Analysis of survival by tumor response. J Clinical Oncology 1:710~719, 1983.
[2] M Buyse and P Piedbois. The relationship between response to treatment and survival time. Stat in Med 15:2797~2812, 1996.
[3] J Crowley and M Hu. Covariance analysis of heart transplant survival data. J American Statistical Assoc, 72:27~36, 1977.
[4] M H Gail. Does cardiac transplantation prolong life? A reassessment. Annals Int Medicine 76:815-17, 1972.
[5] J Kalbfleisch and R Prentice. The statistical analysis of failure time data, second edition. Wiley, 2002.
[6] O’Brien, Peter. A non-parametric test for association with censored data, Biometrics 34:243~250, 1978.
[7] Redmond C, Fisher B, Wieand HS. The methodologic dilemma in retrospectively correlating the amount of chemotherapy received in adjuvant therapy protocols with disease free survival: a commentary. Cancer Treatment Reports 67:519~526, 1983.
[8] S Suissa. Immortal time bias in pharmacoepidemiology. Am J Epi, 167:492-499, 2008.

本文译自Terry Therneau, Cynthia Crowson, Elizabeth Atkinson. Using Time Dependent Covariates and Time Dependent Coecients in the Cox Model. November 26, 2018.
未经同意请勿转载

你可能感兴趣的:(生存分析,算法,r语言)