【问题标题】:R: Days since last event per IDR:自每个 ID 上次事件以来的天数
【发布时间】:2017-10-26 07:42:21
【问题描述】:

我有兴趣查找自上次事件每个 ID 以来的天数。数据如下所示:

df <- data.frame(date=as.Date(
c("06/07/2000","15/09/2000","15/10/2000","03/01/2001","17/03/2001",
"06/08/2010","15/09/2010","15/10/2010","03/01/2011","17/03/2011"), "%d/%m/%Y"), 
event=c(0,0,1,0,1, 1,0,0,0,1),id = c(rep(1,5),rep(2,5)))

         date event id
1  2000-07-06     0  1
2  2000-09-15     0  1
3  2000-10-15     1  1
4  2001-01-03     0  1
5  2001-03-17     1  1
6  2010-08-06     1  2
7  2010-09-15     0  2
8  2010-10-15     0  2
9  2011-01-03     0  2
10 2011-03-17     1  2

我从数据表解决方案here 大量借用,但这不考虑 ID。

library(data.table)
setDT(df)
setkey(df, date,id)

df = df[event == 1, .(lastevent = date), key = date][df, roll = TRUE]
df[, tae := difftime(lastevent, shift(lastevent, 1L, "lag"), unit = "days")]
df[event == 0, tae:= difftime(date, lastevent, unit = "days")]

它生成以下输出

          date  lastevent event id       tae
 1: 2000-07-06       <NA>     0  1   NA days
 2: 2000-09-15       <NA>     0  1   NA days
 3: 2000-10-15 2000-10-15     1  1   NA days
 4: 2001-01-03 2000-10-15     0  1   80 days
 5: 2001-03-17 2001-03-17     1  1  153 days
 6: 2010-08-06 2010-08-06     1  2 3429 days
 7: 2010-09-15 2010-08-06     0  2   40 days
 8: 2010-10-15 2010-08-06     0  2   70 days
 9: 2011-01-03 2010-08-06     0  2  150 days
10: 2011-03-17 2011-03-17     1  2  223 days

然而,我想要的输出如下:

          date  lastevent event id       tae
 1: 2000-07-06       <NA>     0  1   NA days
 2: 2000-09-15       <NA>     0  1   NA days
 3: 2000-10-15 2000-10-15     1  1   NA days
 4: 2001-01-03 2000-10-15     0  1   80 days
 5: 2001-03-17 2001-03-17     1  1  153 days
 6: 2010-08-06 2010-08-06     1  2   NA days
 7: 2010-09-15 2010-08-06     0  2   40 days
 8: 2010-10-15 2010-08-06     0  2   70 days
 9: 2011-01-03 2010-08-06     0  2  150 days
10: 2011-03-17 2011-03-17     1  2  223 days    

唯一的区别是第 6 行和列 tae 中的 NA。 This 是未答复的相关帖子。我看过here,但该解决方案不适用于我的情况。还有许多其他类似的问题,但不是针对每个 ID 的计算。谢谢!

【问题讨论】:

    标签: r data.table time-series


    【解决方案1】:
    df <- data.table(date=as.Date(c("06/07/2000","15/09/2000","15/10/2000","03/01/2001","17/03/2001","06/08/2010","15/09/2010","15/10/2010","03/01/2011","17/03/2011"), 
    "%d/%m/%Y"), event=c(0,0,1,0,1, 1,0,1,0,1),id = c(rep(1,5),rep(2,5)))
    
    tempdt <- df[event==1,]
    
    tempdt[,tae := date - shift(date), by = id]
    
    df <- merge(df, tempdt, by = c("date", "event", "id"), all.x = TRUE)
    
    df[, tae := ifelse(shift(event)==1, date - shift(date), tae), by = id]
    

    编辑

    更通用的解决方案

    df <- data.table(date=as.Date(c("06/07/2000","15/09/2000","15/10/2000","03/01/2001","17/03/2001", "18/03/2001",
                                "06/08/2010","15/09/2010","15/10/2010","03/01/2011","17/03/2011","19/03/2011"), 
                              "%d/%m/%Y"), 
                 event=c(1,0,0,0,0,0,1,1,1,0,1,0),id = c(rep(1,6),rep(5,6)))
    
    ##for event = 1 observations
    tempdt <- df[event==1,]
    
    tempdt[,tae := date - shift(date), by = id]
    
    df <- merge(df, tempdt, by = c("date", "event", "id"), all.x = TRUE)
    
    ##for event = 0 observations
    for(d in df[event==0, date]){
      # print(as.Date(d, origin = "1970-01-01"))
      df[date == d & event == 0, tae := as.Date(d, origin = "1970-01-01") - 
       max(df[date<d & event==1,date]), by = id]  
    }
    

    编辑 2 现在,必须有更快的方法来做到这一点,但如果第一次观察是event = 0,这不会导致任何警告

    df <- data.table(date=as.Date(c("06/07/2000","15/09/2000","15/10/2000","03/01/2001","17/03/2001","06/08/2010","15/09/2010","15/10/2010","03/01/2011","17/03/2011"),
                               "%d/%m/%Y"), event=c(0,0,1,0,1, 1,0,0,0,1),id = c(rep(1,5),rep(2,5))) 
    
    tempdt <- df[event==1,] 
    
    tempdt[,tae := date - shift(date), by = id] 
    
    df <- merge(df, tempdt, by = c("date", "event", "id"), all.x = TRUE) 
    
    for(i in unique(df[,id])){
      # print(i)
      for(d in df[date>df[id == i & event==1,min(date)] & event==0, date]){
      # print(as.Date(d, origin = "1970-01-01"))
        df[id == i & date == d & event == 0,
         tae := as.Date(d, origin = "1970-01-01") - max(df[date<d & 
         event==1,date])]
      }  
    }
    

    【讨论】:

    • 如此简单。这很痛。非常感谢!
    • 只想提一下您的代码不适用于此数据:df
    • 谢谢你一千次。但是,对于我编辑的帖子中的数据集。我收到一些警告。 “在 max.default(numeric(0), na.rm = FALSE) 中:min 没有非缺失参数;返回 -Inf”。一开始就不行....是数据表的原因吗?
    • 我没有收到这些警告。你在使用 data.table 吗?
    • 您好!是的,我使用数据表 1.10-4.rm(list = ls()) df
    猜你喜欢
    • 1970-01-01
    • 2019-02-17
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多