计算当该级别更改时在给定级别上花费的时间

gib*_*z00 5 r zoo dplyr data.table

这就是我的数据帧的样子.最右边的列("TimeForLevelChange")是我想要的列.当给定名称的级别更改时,我想从先前级别获取最小日期,并从发生级别更改的行中取出日期并计算差异.所以在第三排,约翰的等级从1变为2,他在等级1中花了16天(2016-01-17 - 2016-01-01),然后换到等级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)]
Run Code Online (Sandbox Code Playgroud)

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

Fra*_*ank 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]
Run Code Online (Sandbox Code Playgroud)

这使

    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
Run Code Online (Sandbox Code Playgroud)

我使用{.()}而不是.()因为后者给出了错误.我会把它报告为一个bug.