I could do
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]
which gives
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 use {.()} Instead of .() Because the latter gives an error. I will report this as an error.
Frank source share