简化使用tmerge创建的时间相关数据

d7v8vwbk  于 2022-12-20  发布在  其他
关注(0)|答案(3)|浏览(105)

我有一个很大的数据表,包含许多时间依赖变量(50+),用于coxph模型。这个数据集是使用tmerge生成的。患者由patid变量标识,时间间隔由tstart和tstop定义。
我想要拟合的大多数模型仅使用这些时间相关变量中的一个选择。遗憾的是,考克斯比例风险模型的速度取决于数据表中的行数和时间点数,即使这些行中的所有数据都相同。是否有一种好/快的方法可以合并除时间间隔外相同的行,以加快模型的速度?在许多情况下,一行的tstop等于下一行的tstart,在移除一些列之后,其它一切都相同。
例如,我想将data.table示例转换为结果。

library(data.table)
example=data.table(patid = c(1,1,1,2,2,2), tstart=c(0,1,2,0,1,2), tstop=c(1,2,3,1,2,3), x=c(0,0,1,1,2,2), y=c(0,0,1,2,3,3))
results=data.table(patid = c(1,1,2,2), tstart=c(0,2,0,1), tstop=c(2,3,1,3), x=c(0,1,1,2), y=c(0,1,2,3))

这个例子非常简单。我当前的数据集有大约60万名患者,超过20 M行和3.65万个时间点。删除变量应该会显著减少所需的行数,这应该会显著提高使用变量子集进行模型拟合的速度。
我能想到的最好的办法是:

example=data.table(patid = c(1,1,1,2,2,2), tstart=c(0,1,2,0,1,2), tstop=c(1,2,3,1,2,3), x=c(0,0,1,1,2,2), y=c(0,0,1,2,3,3))
example = example[order(patid,tstart),]
example[,matched:=x==shift(x,-1)&y==shift(y,-1),by="patid"]
example[is.na(matched),matched:=FALSE,by="patid"]
example[,tstop:=ifelse(matched,shift(tstop,-1),tstop)]
example[,remove:=tstop==shift(tstop),by="patid"]
example = example[is.na(remove) | remove==FALSE,]
example$matched=NULL
example$remove=NULL

这解决了这个例子;然而,这是相当复杂和多余的代码,当我在数据集中有许多列必须编辑x==shift时(x,-1)为每个变量都是在请求错误。有没有理智的方法来做这件事?列的列表会根据循环改变很多次,因此接受一个列名向量作为输入进行比较将是理想的。t科普一行中包含相同协变量值的多个时段(例如,具有相同协变量值的时段(0,1)、(1,3)、(3,4))

6l7fqoea

6l7fqoea1#

此解决方案基于xy组合的rleid()创建temp永久组ID。使用此临时值,然后将其删除(temp := NULL

example[, .(tstart = min(tstart), tstop = max(tstop), x[1], y[1]), 
        by = .(patid, temp = rleid(paste(x,y, sep = "_")))][, temp := NULL][]
#    patid tstart tstop x y
# 1:     1      0     2 0 0
# 2:     1      2     3 1 1
# 3:     2      0     1 1 2
# 4:     2      1     3 2 3
vq8itlhq

vq8itlhq2#

下面是一个基于我们上面的对话/评论的选项,但允许灵活地设置向量列名:

cols=c("x","y")

cbind(
  example[, id:=rleidv(.SD), .SDcols  = cols][, .(tstart=min(tstart), tstop=max(tstop)), .(patid,id)],
  example[,.SD[1],.(patid,id),.SDcols =cols][,..cols]
)[,id:=NULL][]

输出:

patid tstart tstop x y
1:     1      0     2 0 0
2:     1      2     3 1 1
3:     2      0     1 1 2
4:     2      1     3 2 3
mnowg1ta

mnowg1ta3#

基于Wimpel的回答,我创建了下面的解决方案,它也允许使用列名向量作为输入。

example=data.table(patid = c(1,1,1,2,2,2), tstart=c(0,1,2,0,1,2), tstop=c(1,2,3,1,2,3), x=c(0,0,1,1,2,2), y=c(0,0,1,2,3,3))
variables = c("x","y")
example[,key_ := do.call(paste, c(.SD,sep = "_")),.SDcols = variables]
example[, c("tstart", "tstop") := .(min(tstart),max(tstop)), 
        by = .(patid, temp = rleid(key_))][,key_:=NULL]
example = unique(example)

我可以想象这可以简化,但我认为它做了更复杂的示例所需要的。

相关问题