2016-04-28 50 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 

我用{.()}代替.()因爲後者給出了一個錯誤。我會將它報告爲一個錯誤。