R中随时间变化的系数-怎么做?


17

更新:很抱歉要进行其他更新,但是我发现了一些需要解决的小数多项式和竞争性风险组合的解决方案。


问题

我在R中找不到一种简单的方法来进行时变系数分析。我希望能够将变量系数转换为时变系数(而不是变量),然后绘制随时间变化的图:

βÿ_v一种[R一世一种bË=β0+β1个Ť+β2Ť2

可能的解决方案

1)分割数据集

我看了这个示例(实验课程的第2部分),但是创建一个单独的数据集似乎很复杂,计算量大,而且不是很直观...

2)降级模型-coxvc软件包

coxvc包提供了处理问题的一种优雅的方式-这里有一个手动。问题在于作者不再开发该软件包(最新版本是自2007年5月23日以来),经过一些电子邮件对话,我已经使该软件包起作用,但是我的数据集运行了5个小时(140 000项),并在此期间结束时给出极端估算。您可以在这里找到稍微更新的软件包 -我基本上只是更新了plot函数。

这可能只是一个调整问题,但是由于该软件无法轻松提供置信区间,并且该过程非常耗时,因此我现在正在寻找其他解决方案。

3)timereg包

令人印象深刻的timereg软件包也解决了这个问题,但是我不确定如何使用它,也无法给我一个顺利的过程。

4)分数多项式时间(FPT)模型

我发现Anika Buchholz在“评估随时间变化的疗法和预后因素的长期效果 ”方面的出色论文,在涵盖不同模型方面做得很好。她的结论是,Sauerbrei等人提出的FPT似乎最适合于时间相关系数:

FPT非常擅长检测时变效应,而“降低秩次”方法会导致模型过于复杂,因为它不包括时变效应的选择。

研究似乎很完整,但对我来说却有点遥不可及。自从她碰巧与Sauerbrei合作以来,我还有些纳闷。听起来似乎不错,但我想可以使用mfp软件包进行分析,但是我不确定如何做。

5)cmprsk软件包

我一直在考虑进行竞争性风险分析,但是计算非常耗时,因此我改用常规的Cox回归。该CRR有thoug时间依赖性协变量的选项:

....
cov2        matrix of covariates that will be multiplied 
            by functions of time; if used, often these 
            covariates would also appear in cov1 to give 
            a prop hazards effect plus a time interaction
....

有一个二次方的例子,但是我不太了解时间实际显示的位置,也不确定如何显示它。我也看过了test.R文件,但是示例基本上是相同的...

我的示例代码

这是我用来测试不同可能性的示例

library("survival")
library("timereg")
data(sTRACE)

# Basic cox regression    
surv <- with(sTRACE, Surv(time/365,status==9))
fit1 <- coxph(surv~age+sex+diabetes+chf+vf, data=sTRACE)
check <- cox.zph(fit1)
print(check)
plot(check, resid=F)
# vf seems to be the most time varying

######################################
# Do the analysis with the code from #
# the example that I've found        #
######################################

# Split the dataset according to the splitSurv() from prof. Wesley O. Johnson
# http://anson.ucdavis.edu/~johnson/st222/lab8/splitSurv.ssc
new_split_dataset = splitSuv(sTRACE$time/365, sTRACE$status==9, sTRACE[, grep("(age|sex|diabetes|chf|vf)", names(sTRACE))])

surv2 <- with(new_split_dataset, Surv(start, stop, event))
fit2 <- coxph(surv2~age+sex+diabetes+chf+I(pspline(stop)*vf), data=new_split_dataset)
print(fit2)

######################################
# Do the analysis by just straifying #
######################################
fit3 <- coxph(surv~age+sex+diabetes+chf+strata(vf), data=sTRACE)
print(fit3)

# High computational cost!
# The price for 259 events
sum((sTRACE$status==9)*1)
# ~240 times larger dataset!
NROW(new_split_dataset)/NROW(sTRACE)

########################################
# Do the analysis with the coxvc and   #
# the timecox from the timereg library #
########################################
Ft_1 <- cbind(rep(1,nrow(sTRACE)),bs(sTRACE$time/365,df=3))
fit_coxvc1 <- coxvc(surv~vf+sex, Ft_1, rank=2, data=sTRACE)

fit_coxvc2 <- coxvc(surv~vf+sex, Ft_1, rank=1, data=sTRACE)

Ft_3 <- cbind(rep(1,nrow(sTRACE)),bs(sTRACE$time/365,df=5))
fit_coxvc3 <- coxvc(surv~vf+sex, Ft_3, rank=2, data=sTRACE)

layout(matrix(1:3, ncol=1))
my_plotcoxvc <- function(fit, fun="effects"){
    plotcoxvc(fit,fun=fun,xlab='time in years', ylim=c(-1,1), legend_x=.010)
    abline(0,0, lty=2, col=rgb(.5,.5,.5,.5))
    title(paste("B-spline =", NCOL(fit$Ftime)-1, "df and rank =", fit$rank))
}
my_plotcoxvc(fit_coxvc1)
my_plotcoxvc(fit_coxvc2)
my_plotcoxvc(fit_coxvc3)

# Next group
my_plotcoxvc(fit_coxvc1)

fit_timecox1<-timecox(surv~sex + vf, data=sTRACE)
plot(fit_timecox1, xlab="time in years", specific.comps=c(2,3))

代码显示在以下图表中:比较coxvc不同设置以及 coxvc和timecox图的设置。我想结果还可以,但是我认为我无法解释timecox图-看起来很复杂...

我的(当前)问题

  • 如何在R中进行FPT分析?
  • 如何在cmprsk中使用时间协变量?
  • 如何绘制结果(最好是置信区间)?

3
链接中的示例是关于时变协变量,而不是时变系数。这些太不一样了。为了得到时变参数描述你使用互动的方式,即不再以模型,拟合模型ÿ = X β 0ÿ=Xβÿÿ=Xβ0+XŤβ1个+XŤ2β2y~xy~x*(t+t^2)-ty~x+x:t+x:t^2

我认为第二部分是“ 2.检查PH假设的模型确定性时变协变量”将是处理我的问题的部分。我希望做一些您所描述的公式,但是当我尝试它时,我遇到了错误或者单独的时间变量...但是,我得到的时间p值偏低:-D
Max Gordon

@ max-gordon,您的响应变量是一个数量,还是直到出现偶数为止的时间?因为您引用的大多数方法都是专门针对事件时间数据的。
f1r3br4nd

@ f1r3br4nd:这是一个危害(不是按比例)的数量(在我的研究中为年龄),即在我的事件发生时间模型中,危害随时间变化。最后,我决定分为两个不同的时间范围,因为我对制作3-D图并不感到兴奋-从来没有通过审阅者...
Max Gordon

时间相关/可变预测变量和时间交互之间存在差异。大多数变量是时间相关的(性例外)。如果您每个人只有一个观察,那么您将几乎没有机会进行时间相关/不同的分析。安德森·吉尔(Anderson-Gill)的方法是时间依赖性生存分析最常用的方法。时间依赖性方法的优点是,随访期间的值可能比基线值更能预测生存经验。第二种情况是时间相互作用的预测因素,只是对PH假设的检验。
亚当·罗宾逊

Answers:


8

@mpiktas在提供可行的模型时接近,但是需要将time = t中的二次项使用的术语是I(t^2))。之所以如此,是因为在R中,“ ^”的公式解释创建了相互作用并且不执行幂运算,因此“ t”与“ t”的相互作用只是“ t”。(这是否应该使用[r]标签迁移到SO?)

对于此过程的替代方案(在我看来,对于推理的目的有些怀疑),并且可能很适合您在Harrell rms / Hmisc软件包中使用支持功能的兴趣,请参阅Harrell的“回归建模策略”。他提到(但只是顺便说一句,尽管他确实引用了一些自己的论文)只是建立了与时间尺度相适应的样条曲线,以模拟浴缸状的危害。他关于参数生存模型的章节描述了各种绘图技术,用于检查比例风险假设并检查时间尺度上估计对数风险影响的线性。

编辑:另一个选项是使用coxph描述为“时间转换函数的可选列表”的'tt'参数。


我同意应该将其移至SO [r]标签。
扎克(Zach)

+1为您的答案,我不知道这会很难回答。这似乎是一个常见的问题,也许这个问题更多是编码问题,而不是SO是一个更好的选择。我尝试了您的公式,似乎vf + I(vf log(time))非常适合,我只尝试了vf time和vf * time ^ 2,但对数给出的票价是最低的p值。我试图用cph()函数运行它以获取AIC,但它给出了一个错误:(您是否知道如何对估算值进行绘图?
Max Gordon

我认为,check <- cox.zph(fit1); print(check); plot(check, resid=F)就像您设置的那样,给出了有关“效果”时间的信息图。您是说rms软件包中的cph()还是生存中的coxph?
DWin 2011年

是的,Schoenfeld残差的确可以很好地了解时间变化,但我认为人们可能很难理解它。据我了解,该图给出了模型未解释的残留变化。我想要一个在y轴上具有完全可变影响并且在x轴上具有时间完全可变影响的图,我相信这将更容易解释,因为您不必同时查看表格和图在特定时间点获取危害...是的,我的意思是cph()而不是coxph(),因为那与AIC()不兼容
Max Gordon

我也对为什么我发现问题中描述的所有复杂方法感到有些困惑,而我(变量*时间)似乎非常简单直观-作为我正在考虑的非统计学家,我错过了什么?
Max Gordon

5

我已经更改了答案,因为@DWin或@Zach的答案都不能完全回答如何对时变系数建模。我最近写了一个帖子关于这一点。这是要点。

核心概念 HŤ

HŤ=FŤ小号Ť

FŤ小号Ť0

Ť一世Ë0小号Ť

当允许对象在其他时间点进入时,我们必须Surv将从更改Surv(time, status)Surv(start_time, end_time, status)。尽管end_time与结果密切相关,但start_time现在可以将其作为一个交互项(正如原始建议中所暗示的)。在常规设置中,start_time除稍后出现的一些主题外,该值是0,但我们将每个观察值分成几个周期,我们突然有很多非零的开始时间。唯一的区别是,每个观察都发生多次,除了最后一个观察之外,所有观察都可以选择未经审查的结果。

实践中的时间分割

我刚刚在CRAN上发布了Greg软件包,该软件包使时间分割变得容易。首先,我们从一些理论观察开始:

library(Greg)
test_data <- data.frame(
  id = 1:4,
  time = c(4, 3.5, 1, 5),
  event = c("censored", "dead", "alive", "dead"),
  age = c(62.2, 55.3, 73.7, 46.3),
  date = as.Date(
    c("2003-01-01", 
      "2010-04-01", 
      "2013-09-20",
      "2002-02-23"))
)

我们可以用*表示事件的图形显示:

在此处输入图片说明

如果我们应用timeSplitter以下内容:

library(dplyr)
split_data <- 
  test_data %>% 
  select(id, event, time, age, date) %>% 
  timeSplitter(by = 2, # The time that we want to split by
               event_var = "event",
               time_var = "time",
               event_start_status = "alive",
               time_related_vars = c("age", "date"))

我们得到以下内容:

在此处输入图片说明

如您所见,每个对象已被拆分为多个事件,其中最后一个时间跨度包含实际事件状态。这使我们现在可以构建具有简单:交互项的模型(不要使用,*因为它会扩展为,time + var + time:var并且我们对时间本身不感兴趣)。无需使用I()函数,尽管如果您要检查随时间变化的非线性,我通常会创建一个单独的时间交互变量,在其中添加样条线,然后使用显示rms::contrast。无论如何,您的回归调用现在应如下所示:

coxp(Surv(start_time, end_time, event) ~ var1 + var2 + var2:time, 
     data = time_split_data)

使用生存包的tt功能

还有一种使用tt函数直接在生存包中对时间相关系数建模的方法。Therneau教授在他的小插图中对该主题进行了详尽的介绍。不幸的是,由于内存限制,在大型数据集中很难做到这一点。似乎该tt函数将时间分割成非常细小的片段,在此过程中生成了巨大的矩阵。


2

您可以在以下位置使用apply.rolling函数 PerformanceAnalytics中通过滚动窗口运行线性回归,这将使您的系数随时间变化。

例如:

library(PerformanceAnalytics)
library(quantmod)
getSymbols(c('AAPL','SPY'), from='01-01-1900')
chart.RollingRegression(Cl(AAPL),Cl(SPY), width=252, attribute='Beta')
#Note: Alpha=y-intercept, Beta=regression coeffient

这也可以与其他功能一起使用。


谢谢您的回答,我想一个移动的时间窗口应该和我的方法一样有效。不过,我无法运行您的示例,请基于我的TRACE示例给出一个示例,以便我确切地知道如何实现它吗?
Max Gordon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.