我见过类似的其他问题,但他们没有回答我的问题。我想扩展我的数据集,因为我需要为生存分析创建一个时变变量,并希望使用survSplit
命令(survival
包)但我的数据已经部分采用长格式。示例数据:
data1<-structure(list(id = c(1, 1, 1, 1, 5, 5, 5, 5, 5, 7, 7, 7, 7,
7, 7), start = c(0, 183, 210, 241, 0, 183, 187, 212, 244, 0,
118, 139, 188, 212, 237), no_days = c(NA, 28L, 28L, 28L, NA,
7L, 28L, 28L, 28L, NA, 28L, 28L, 28L, 28L, 28L), stop = c(NA,
211, 238, 269, NA, 190, 215, 240, 272, NA, 146, 167, 216, 240,
265), drug = c(0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1),
dead = c(0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1)), .Names = c("id",
"start", "no_days", "stop", "drug", "dead"), row.names = c(NA,
15L), class = "data.frame")
> head(data1,15)
id start no_days stop drug dead
1 1 0 NA NA 0 0
2 1 183 28 211 1 0
3 1 210 28 238 1 0
4 1 241 28 269 1 1
5 5 0 NA NA 0 0
6 5 183 7 190 1 0
7 5 187 28 215 1 0
8 5 212 28 240 1 0
9 5 244 28 272 1 1
10 7 0 NA NA 0 0
11 7 118 28 146 1 0
12 7 139 28 167 1 0
13 7 188 28 216 1 0
14 7 212 28 240 1 0
15 7 237 28 265 1 1
Start
是药物开处方的日期,no_days
是处方用了多长时间,drug
表示一个人是否在给定时间段内服用了药物(这是我需要变量的变量),dead
表示一个人何时死亡。目前,数据集仅包含个体在药物上的时间,因此我想要的最终数据集应如下所示:
head(data1,18)
id start no_days stop drug dead
1 1 0 NA 182 0 0
2 1 183 28 211 1 0
3 1 210 28 238 1 0
4 1 239 NA 240 0 0
5 1 241 28 269 1 1
6 5 0 NA 182 0 0
7 5 183 7 190 1 0
8 5 187 28 215 1 0
9 5 212 28 240 1 0
10 5 241 NA 243 0 0
11 5 244 28 272 1 1
12 7 0 NA 117 0 0
13 7 118 28 146 1 0
14 7 139 28 167 1 0
15 7 168 NA 187 0 0
16 7 188 28 216 1 0
17 7 212 28 240 1 0
18 7 237 28 265 1 1
也许这应该是一个标准的数据操作问题,我需要根据某个标准添加更多的行,但考虑到它是生存数据而survSplit
是为此而设计的,尽管数据结构略有不同我想知道是否有一种简单的方法可以使用survSplit
来解决我的问题。如果没有,是否有人有一个简单的建议来扩展数据帧。
我的最终步骤是适合像:
这样的cox模型coxph(Surv(data$start,data$stop,data$dead)~covariates + drug +cluster(id),data=data1)
感谢您的任何建议。
答案 0 :(得分:1)
考虑以下数据与基础R争论,其中基本上你merge
数据框本身移动了一行以对齐当前和下一条记录,然后transform
为开始和< em>停止计算。
注意:merge
会引发重复的nextidcnt
列的警告(而不是错误)。使用data1
和id
(在新df中移位一个)作为连接键忽略或创建合并的第二个idcnt
。
# OBTAIN GROUP COUNT (FOR MERGE IDs)
data1$idcnt <- sapply(1:nrow(data1), function(i) sum(data1[1:i, c("id")] == data1$id[i]))
data1$nextidcnt <- data1$idcnt + 1
# MERGE
dfm <- merge(data1, data1, by.x=c("id", "nextidcnt"), by.y=c("id", "idcnt"))
# CALCULATE NEW COLUMNS
dfm <- transform(dfm,
start = ifelse(is.na(stop.x), start.x, stop.x + 1),
no_days = no_days.x,
stop = start.y - 1,
drug = 0,
dead = dead.x)
# ROW BIND ORIGINAL SUBSET WITH NEW ROWS
finaldf <- rbind(data1[data1$start != 0, c(1:6)],
dfm[dfm$start < dfm$stop,
c("id", "start", "no_days", "stop", "drug", "dead")])
finaldf <- finaldf[with(finaldf, order(id, start, stop)),] # ORDER BY ID, START, STOP
rownames(finaldf) <- NULL # RESET ROW NAMES
<强>输出强>
finaldf
# id start no_days stop drug dead
# 1 1 0 NA 182 0 0
# 2 1 183 28 211 1 0
# 3 1 210 28 238 1 0
# 4 1 239 28 240 0 0
# 5 1 241 28 269 1 1
# 6 5 0 NA 182 0 0
# 7 5 183 7 190 1 0
# 8 5 187 28 215 1 0
# 9 5 212 28 240 1 0
# 10 5 241 28 243 0 0
# 11 5 244 28 272 1 1
# 12 7 0 NA 117 0 0
# 13 7 118 28 146 1 0
# 14 7 139 28 167 1 0
# 15 7 168 28 187 0 0
# 16 7 188 28 216 1 0
# 17 7 212 28 240 1 0
# 18 7 237 28 265 1 1