You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何合并tmerge生成的时变数据行以加速coxph模型拟合?

问题

我有一个通过tmerge生成的大型data.table,包含50余个时变变量,用于coxph模型拟合。数据集以patid标识患者,时间区间由tstart和tstop定义。多数模型仅需使用部分时变变量,但coxph模型的运行速度受数据集行数和时间点数量影响——即使行内除时间区间外的数据完全相同,仍会拖慢速度。

我需要一种高效的方法,合并那些除时间区间外指定协变量完全相同的连续行,以提升模型拟合速度。例如需将如下示例data.table转换为results:

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万患者、2000万行、3650个时间点,合并行后应能显著提升模型速度。我目前的实现方法如下:

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

但该方法代码复杂,且需逐个修改协变量判断逻辑,易出错;同时无法处理连续多个协变量值相同的时间区间。我希望能有更合理的实现方式,支持传入协变量列名向量作为输入(因列名会随循环变化)。

解决方案

针对需求,这里提供一种基于data.table分组和游程编码的高效实现,支持动态传入协变量列名,且能处理任意数量的连续相同协变量行:

library(data.table)

# 定义合并函数
merge_consecutive_rows <- function(dt, covar_cols) {
  # 确保按患者和时间起点排序
  setorder(dt, patid, tstart)
  
  # 按患者分组,标记连续相同协变量的组
  dt[, group := rleidv(.SD), by = patid, .SDcols = covar_cols]
  
  # 按患者和组聚合,取每组的第一个tstart、最后一个tstop,协变量取组内任意值(因为组内相同)
  merged_dt <- dt[, .(
    tstart = first(tstart),
    tstop = last(tstop),
    .SD
  ), by = .(patid, group), .SDcols = covar_cols]
  
  # 去重协变量列(因为组内每行都一样,聚合后会重复)
  merged_dt <- unique(merged_dt, by = c("patid", "group"))
  
  # 移除临时分组列,按patid和tstart重新排序
  merged_dt[, group := NULL]
  setorder(merged_dt, patid, tstart)
  
  return(merged_dt)
}

# 测试示例
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 <- merge_consecutive_rows(example, covar_cols = c("x", "y"))
print(results)

代码说明

  • 排序保障:先用setorder确保数据按patid和tstart排序,保证连续行是时间上的先后顺序。
  • 游程编码分组:使用rleidv函数,按指定协变量列对每个患者的行进行游程编码——连续相同协变量的行会被分配同一个group值,完美解决连续多组相同的问题。
  • 聚合合并:按patid和group分组,取每组的第一个tstart(区间起点)、最后一个tstop(区间终点),协变量直接保留组内值(因为组内所有行的协变量都相同)。
  • 高效性:整个过程基于data.table的底层优化,适合处理千万级别的大数据,避免了循环和逐行判断的低效操作。

适配场景

你可以在循环中动态传入不同的协变量列名向量,比如:

# 循环处理不同的协变量组合
covar_list <- list(c("x", "y"), c("x"), c("y", "z"))
for (covars in covar_list) {
  merged_data <- merge_consecutive_rows(your_large_dt, covar_cols = covars)
  # 后续拟合coxph模型...
}

内容的提问来源于stack exchange,提问作者D. Stevens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 18:20:32