根据条件从不同的列中过滤日期

时间:2018-08-22 00:52:56

标签: r conditional-statements mutate

我的数据集示例:

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,我想获得一列日期,其中:

  1. 如果intervention == 1,则返回此行的admidatelast_adm==1之间的时差。
  2. 如果为intervention == 0,则返回admidate的{​​{1}}和first_adm==1的{​​{1}}时的时间。

每个id只有一个last_adm==1和一个id

目的是获得跟踪时间,以便在两组之间进行比较。首先,当他们进行“干预”时就开始了。对于其他没有干预的人,它从第一次接触开始。

id最终看起来像这样:

first_adm

1 个答案:

答案 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(),但我们仍在这里使用idid,因为我们正在按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升序来对数据集进行排序。