计算在给定级别更改时花费在给定级别的时间
Calculating time spent in a given level when that level changes
这就是我的数据框的外观 like.The 最右边的列 ("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)]
我可以在 data.table 中使用 shift 函数,但我不知道如何为给定名称定义上一级的最小日期。
我可能会
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
我用的是{.()}
而不是.()
,因为后者报错。我会将其报告为错误。
这就是我的数据框的外观 like.The 最右边的列 ("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)]
我可以在 data.table 中使用 shift 函数,但我不知道如何为给定名称定义上一级的最小日期。
我可能会
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
我用的是{.()}
而不是.()
,因为后者报错。我会将其报告为错误。