r 累积和函数,条件
r cumulative sum function, conditions
我在 R 中有一个数据框,相当大 600 rows/observations
一列 patientId
不是数字形式,例如 ju89、ju87,所以它是一个因子列
一栏是remission
1/0,其中1表示缓解0表示未缓解
一栏是timefromdiagnosis
现在,从诊断开始,患者从 1 到 0、0 到 0、0 到 1 或 1 到 1
我想在数据框中添加一列
- 1 当患者有 0 个缓解
- 2 当恰好患者有 1 个缓解并且他最后一次有 0 或有 1 个缓解并且他最后一次有 1 个缓解或有 1 个缓解并且这是他的第一次观察
- 3 当患者有 1 次缓解并且最近 2 次或更多次有 1 次缓解时
我在 plyr
中研究过用 cum sum 来做这个,但它不适合我想做的或者不太清楚如何适应
数据框已经排序,因此患者 ID 彼此相邻,并且随着您向下阅读数据框,每个患者的诊断时间都会增加
由于保密原因,我无法提供数据框,但在这里可以澄清一些事情
remission timefromdiag patientid ...(other variables)
这是我开始使用的数据:
patientId timefromdiagnosis remission
ju67 1.2 1
ju67 1.6 0
ju67 3 0
ju88 1.5 1
ju88 2 1
ju23 1.9 1
ju23 5 0
这是我想要得到的,疾病阶段是我想要的栏目:
patientId timefromdiagnosis remission disease stage
ju67 1.2 1 2
ju67 1.6 0 1
ju67 3 0 1
ju88 1.5 1 2
ju88 2 1 2
ju23 1.9 1 2
ju23 5 0 1
ju38 1.7 1 2
ju38 1.9 1 2
ju38 3 1 3
ju38 4 1 3
ju38 5 0 1
注意患者 ju38
是如何达到 3 的,因为他已经连续 3 次缓解,包括现在的时间(缓解过去两次和现在),然后他保持在 3,因为他只是有另一个缓解,然后他去了到疾病 1 期,因为他的缓解率为 0。
患者 ju88
在 t=2 时缓解,并且在上次 t=1.5 时缓解,但这只是连续两次缓解,包括 t=2,所以他处于疾病阶段 2
患者 ju23
在 t=1.9,缓解为 1,这是对他的第一次观察,因此他满足疾病阶段 2 的标准,如果他的缓解为 0,他将处于疾病状态第一阶段
您正在使用患者处于缓解期的连续周期数,并在患者缓解后重置该计数器。因此,我认为缓解变量的 运行 长度编码很有意义。您可以使用 rle
函数计算它:
dat$diseaseStage <- ave(dat$remission, dat$patientId, FUN=function(x) {
ret <- unlist(lapply(rle(x)$length, function(y) c(rep(2, min(2, y)), rep(3, max(0, y-2)))))
ret[x == 0] <- 1
ret
})
dat
# patientId timefromdiagnosis remission diseaseStage
# 1 ju67 1.2 1 2
# 2 ju67 1.6 0 1
# 3 ju67 3.0 0 1
# 4 ju88 1.5 1 2
# 5 ju88 2.0 1 2
# 6 ju23 1.9 1 2
# 7 ju23 5.0 0 1
# 8 ju38 1.7 1 2
# 9 ju38 1.9 1 2
# 10 ju38 3.0 1 3
# 11 ju38 4.0 1 3
# 12 ju38 5.0 0 1
请注意,这适用于患者多次进入和退出缓解的更复杂的情况:
dat2 <- data.frame(patientId=rep("x", 12), remission=rep(c(1, 0, 1, 0), each=3))
使用相同的函数,我们得到:
# patientId remission diseaseStage
# 1 x 1 2
# 2 x 1 2
# 3 x 1 3
# 4 x 0 1
# 5 x 0 1
# 6 x 0 1
# 7 x 1 2
# 8 x 1 2
# 9 x 1 3
# 10 x 0 1
# 11 x 0 1
# 12 x 0 1
请注意,在这种情况下,使用 cumsum
是不够的,因为它不会接受我们在第 4-6 行中已经康复的事实。
我在 R 中有一个数据框,相当大 600 rows/observations
一列 patientId
不是数字形式,例如 ju89、ju87,所以它是一个因子列
一栏是remission
1/0,其中1表示缓解0表示未缓解
一栏是timefromdiagnosis
现在,从诊断开始,患者从 1 到 0、0 到 0、0 到 1 或 1 到 1
我想在数据框中添加一列
- 1 当患者有 0 个缓解
- 2 当恰好患者有 1 个缓解并且他最后一次有 0 或有 1 个缓解并且他最后一次有 1 个缓解或有 1 个缓解并且这是他的第一次观察
- 3 当患者有 1 次缓解并且最近 2 次或更多次有 1 次缓解时
我在 plyr
中研究过用 cum sum 来做这个,但它不适合我想做的或者不太清楚如何适应
数据框已经排序,因此患者 ID 彼此相邻,并且随着您向下阅读数据框,每个患者的诊断时间都会增加
由于保密原因,我无法提供数据框,但在这里可以澄清一些事情
remission timefromdiag patientid ...(other variables)
这是我开始使用的数据:
patientId timefromdiagnosis remission
ju67 1.2 1
ju67 1.6 0
ju67 3 0
ju88 1.5 1
ju88 2 1
ju23 1.9 1
ju23 5 0
这是我想要得到的,疾病阶段是我想要的栏目:
patientId timefromdiagnosis remission disease stage
ju67 1.2 1 2
ju67 1.6 0 1
ju67 3 0 1
ju88 1.5 1 2
ju88 2 1 2
ju23 1.9 1 2
ju23 5 0 1
ju38 1.7 1 2
ju38 1.9 1 2
ju38 3 1 3
ju38 4 1 3
ju38 5 0 1
注意患者 ju38
是如何达到 3 的,因为他已经连续 3 次缓解,包括现在的时间(缓解过去两次和现在),然后他保持在 3,因为他只是有另一个缓解,然后他去了到疾病 1 期,因为他的缓解率为 0。
患者 ju88
在 t=2 时缓解,并且在上次 t=1.5 时缓解,但这只是连续两次缓解,包括 t=2,所以他处于疾病阶段 2
患者 ju23
在 t=1.9,缓解为 1,这是对他的第一次观察,因此他满足疾病阶段 2 的标准,如果他的缓解为 0,他将处于疾病状态第一阶段
您正在使用患者处于缓解期的连续周期数,并在患者缓解后重置该计数器。因此,我认为缓解变量的 运行 长度编码很有意义。您可以使用 rle
函数计算它:
dat$diseaseStage <- ave(dat$remission, dat$patientId, FUN=function(x) {
ret <- unlist(lapply(rle(x)$length, function(y) c(rep(2, min(2, y)), rep(3, max(0, y-2)))))
ret[x == 0] <- 1
ret
})
dat
# patientId timefromdiagnosis remission diseaseStage
# 1 ju67 1.2 1 2
# 2 ju67 1.6 0 1
# 3 ju67 3.0 0 1
# 4 ju88 1.5 1 2
# 5 ju88 2.0 1 2
# 6 ju23 1.9 1 2
# 7 ju23 5.0 0 1
# 8 ju38 1.7 1 2
# 9 ju38 1.9 1 2
# 10 ju38 3.0 1 3
# 11 ju38 4.0 1 3
# 12 ju38 5.0 0 1
请注意,这适用于患者多次进入和退出缓解的更复杂的情况:
dat2 <- data.frame(patientId=rep("x", 12), remission=rep(c(1, 0, 1, 0), each=3))
使用相同的函数,我们得到:
# patientId remission diseaseStage
# 1 x 1 2
# 2 x 1 2
# 3 x 1 3
# 4 x 0 1
# 5 x 0 1
# 6 x 0 1
# 7 x 1 2
# 8 x 1 2
# 9 x 1 3
# 10 x 0 1
# 11 x 0 1
# 12 x 0 1
请注意,在这种情况下,使用 cumsum
是不够的,因为它不会接受我们在第 4-6 行中已经康复的事实。