2016-04-28 5 views
5

So sieht mein Datenframe aus. Die rechte Spalte ("TimeForLevelChange") ist meine gewünschte Spalte. Wenn sich ein Level für einen bestimmten Namen ändert, möchte ich das Mindestdatum von der vorherigen Ebene nehmen und das Datum aus der Zeile nehmen, in der die Leveländerung stattfindet, und die Differenz berechnen. So auf der dritten Reihe, änderte John Niveau von 1 bis 2 und er verbrachte 16 Tage (2016.01.17 - 2016.01.01) in Stufe 1 vor dem Pegeländerungs 2.Berechnung der Zeit, die in einer bestimmten Ebene verbracht wird, wenn sich dieser Pegel ändert

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

I Verschiebung verwenden können Funktion in data.table, aber ich weiß nicht, wie man das Mindestdatum von der vorherigen Ebene für einen gegebenen Namen definiert.

Antwort

7

könnte ich

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] 

tun, die

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 

I {.()} statt .() verwenden gibt, weil dieser einen Fehler gibt. Ich werde es als Fehler melden.