2016-04-28 60 views
5

这是我的数据框的样子。最右边的列(“TimeForLevelChange”)是我期望的列。当给定名称的级别发生变化时,我想从上一级别中获取最小日期,并从发生级别更改的行中获取日期并计算差异。因此,在第三排,约翰的水平从1改为2,他用了16天(2016年1月17日 - 2016年1月1日)改变为前水平在1级2计算在该级别更改时给定级别上花费的时间

library(data.table) 
     dt <- fread(' 
      Name  Level  Date   RecentLevelChange TimeForLevelChange 
      John  1  2016-01-01  NA     NA 
      John  1  2016-01-10  NA     NA 
      John  2  2016-01-17  1->2    16 
      John  2  2016-01-18  NA     NA 
      John  3  2016-01-22  2->3    5 
      John  4  2016-01-26  3->4    4 
      John  4  2016-01-27  NA     NA 
      John  7  2016-01-29  4->7    3 
      Tom  1  2016-01-10  NA    NA 
      Tom  2  2016-01-17  1->2    7 
      Tom  2  2016-01-18  NA    NA 
      Tom  3  2016-01-22  2->3    5 
      Tom  4  2016-01-26  3->4    4 
      Tom  4  2016-01-27  NA    NA 
      Tom  7  2016-01-29  4->7    3 
     ') 
dt[, Date := as.IDate(Date)] 

我可以用shift函数在data.table中,但我不知道如何定义给定名称的先前级别的最小日期。

回答

7

我可能会做

spell = dt[,{.(
    w = .I[1L], 
    Date = Date[1L] 
)}, by=.(Name, rleid(Level))][, .(
    w = tail(w,-1), 
    d = diff(Date) 
), by=Name] 

dt[spell$w, dur_lastspell := spell$d] 

这给

Name Level  Date RecentLevelChange TimeForLevelChange dur_lastspell 
1: John  1 2016-01-01    NA     NA  NA days 
2: John  1 2016-01-10    NA     NA  NA days 
3: John  2 2016-01-17    1->2     16  16 days 
4: John  2 2016-01-18    NA     NA  NA days 
5: John  3 2016-01-22    2->3     5  5 days 
6: John  4 2016-01-26    3->4     4  4 days 
7: John  4 2016-01-27    NA     NA  NA days 
8: John  7 2016-01-29    4->7     3  3 days 
9: Tom  1 2016-01-10    NA     NA  NA days 
10: Tom  2 2016-01-17    1->2     7  7 days 
11: Tom  2 2016-01-18    NA     NA  NA days 
12: Tom  3 2016-01-22    2->3     5  5 days 
13: Tom  4 2016-01-26    3->4     4  4 days 
14: Tom  4 2016-01-27    NA     NA  NA days 
15: Tom  7 2016-01-29    4->7     3  3 days 

我用{.()}代替.()因为后者给出了一个错误。我会将它报告为一个错误。