2016-04-28 12 views
5

Questo è l'aspetto del mio dataframe. La colonna più a destra ("TimeForLevelChange") è la colonna desiderata. Quando un livello cambia per un determinato Nome, voglio prendere la data minima dal livello precedente e prendere la data dalla riga in cui avviene il cambio di livello e calcolare la differenza. Così il terza fila, il livello di John cambiato 1-2 e ha passato 16 giorni (2016-01-17 - 2016/01/01) nel livello 1 prima di passare al livello 2.Calcolo del tempo trascorso in un dato livello quando quel livello cambia

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)] 

posso usare lo spostamento funzione in data.table ma non so come definire la data minima dal livello precedente per un determinato nome.

risposta

7

potrei fare

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] 

che 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 

io uso {.()} invece di .() perché quest'ultimo dà un errore. Lo segnalerò come un bug.