我的数据集示例:
library('lubridate')
id<-c(1,1,2,2,2,3,3,3)
admidate<-c(dmy('01/01/2010', '01/01/2011', '01/02/2010', '01/02/2011', '01/01/2012', '01/01/2010', '01/03/2010', '01/03/2011'))
disdate<-c(dmy('15/01/2010', '15/01/2011', '15/02/2010', '15/02/2011', '15/02/2012', '15/01/2010', '15/03/2010', '15/03/2011'))
first_adm<-c(1,0,1,0,0,1,0,0)
last_adm<-c(0,1,0,0,1,0,0,1)
intervention<-c(1,0,0,1,0,0,0,0)
df<-data.frame(id, admidate, disdate, first_adm, last_adm, intervention)
对于每个id
,我想获得一列日期,其中:
intervention == 1
,则返回此行的admidate
与last_adm==1
之间的时差。 intervention == 0
,则返回admidate
的{{1}}和first_adm==1
的{{1}}时的时间。 每个id
只有一个last_adm==1
和一个id
。
目的是获得跟踪时间,以便在两组之间进行比较。首先,当他们进行“干预”时就开始了。对于其他没有干预的人,它从第一次接触开始。
id
最终看起来像这样:
first_adm
答案 0 :(得分:2)
这就是我会尝试使用首选工具的方式。
data.table
版本library(data.table)
setDT(df)[, {
fa <- first(admidate[first_adm == 1])
la <- last(admidate[last_adm == 1])
fi <- first(admidate[intervention == 1])
ai <- any(intervention == 1)
.(fu_time = la - if (ai) pmax(fa, fi) else fa)
}, by = id]
只是返回每个id
id fu_time 1: 1 365 days 2: 2 334 days 3: 3 424 days
请注意,尽管OP保证每个first()
仅包含一个last()
,但我们仍在这里使用id
和id
,因为我们正在按first_adm
进行汇总只有一个last_adm
。
但是,OP希望更新原始的df
。使用data.table
,我们可以追加一个新列,其中每一行包含相应组的结果:
setDT(df)[, fu_time := {
fa <- first(admidate[first_adm == 1])
la <- last(admidate[last_adm == 1])
fi <- first(admidate[intervention == 1])
ai <- any(intervention == 1)
la - if (ai) pmax(fa, fi) else fa
}, by = id]
现在,原始df
已更新:
df[]
id admidate disdate first_adm last_adm intervention fu_time 1: 1 2010-01-01 2010-01-15 1 0 1 365 days 2: 1 2011-01-01 2011-01-15 0 1 0 365 days 3: 2 2010-02-01 2010-02-15 1 0 0 334 days 4: 2 2011-02-01 2011-02-15 0 0 1 334 days 5: 2 2012-01-01 2012-02-15 0 1 0 334 days 6: 3 2010-01-01 2010-01-15 1 0 0 424 days 7: 3 2010-03-01 2010-03-15 0 0 0 424 days 8: 3 2011-03-01 2011-03-15 0 1 0 424 days
如果仅最后一行包含每个id
的结果,并且我们要完全模拟OP的预期结果:
setDT(df)[, fu_time := {
fa <- first(admidate[first_adm == 1])
la <- last(admidate[last_adm == 1])
fi <- first(admidate[intervention == 1])
ai <- any(intervention == 1)
replace(rep("-", .N), .N, la - if (ai) pmax(fa, fi) else fa)
}, by = id]
df[]
id admidate disdate first_adm last_adm intervention fu_time 1: 1 2010-01-01 2010-01-15 1 0 1 - 2: 1 2011-01-01 2011-01-15 0 1 0 365 3: 2 2010-02-01 2010-02-15 1 0 0 - 4: 2 2011-02-01 2011-02-15 0 0 1 - 5: 2 2012-01-01 2012-02-15 0 1 0 334 6: 3 2010-01-01 2010-01-15 1 0 0 - 7: 3 2010-03-01 2010-03-15 0 0 0 - 8: 3 2011-03-01 2011-03-15 0 1 0 424
dplyr
版本由于OP用 mutate 标记了问题,我想OP可能更喜欢使用dplyr
方法:
library(dplyr)
df %>%
group_by(id) %>%
summarise(
fu_time = last(admidate[last_adm == 1]) -
if (any(intervention == 1))
pmax(first(admidate[first_adm == 1]), first(admidate[intervention == 1]))
else first(admidate[first_adm == 1])
) %>%
inner_join(df, .)
id admidate disdate first_adm last_adm intervention fu_time 1 1 2010-01-01 2010-01-15 1 0 1 365 days 2 1 2011-01-01 2011-01-15 0 1 0 365 days 3 2 2010-02-01 2010-02-15 1 0 0 334 days 4 2 2011-02-01 2011-02-15 0 0 1 334 days 5 2 2012-01-01 2012-02-15 0 1 0 334 days 6 3 2010-01-01 2010-01-15 1 0 0 424 days 7 3 2010-03-01 2010-03-15 0 0 0 424 days 8 3 2011-03-01 2011-03-15 0 1 0 424 days
请注意,这不会更新df
,但会创建一个新对象。
隐含地假定通过在每个admidate
组中将id
升序来对数据集进行排序。