【发布时间】:2020-08-12 13:30:20
【问题描述】:
我有一个大约 150 万行和数百列的数据表结构,表示带有赛马结果的日期 - 这将用于预测模型,但首先需要特征工程来计算各种实体的罢工率创造前一天每场比赛的先前记录的条款。
“击球率”可以用多种方式定义,但一个简单的方式是任何给定马匹、驯马师、骑师等的获胜次数与跑步次数的比率。当然,这必须考虑到所有之前的跑步和获胜次数,但是不包括“今天”的结果,因为这对于构建模型来说是无稽之谈。
不管怎样,根据网上一些例子改编的简化数据结构就足够解释了。
生成数据如下:
n <- 90
dt <- data.table(
date=rep(seq(as.Date('2010-01-01'), as.Date('2015-01-01'), by='year'), n/6),
finish=c(1:5),
trainer=sort(rep(letters[1:5], n/5))
)
想象一下,在这些日期,每个训练师都有一个跑步者,其在比赛中的完赛位置用“完成”表示。对于序列中的新日期(但不在此数据中),到目前为止赢得的次数的比率可以这样计算:
dt[order(trainer, date), .(strike_rate = sum(finish==1)/.N), by=trainer]
但是,为每位培训师显示的最终罢工率变量仅对不在此数据集中的序列中的新日期有效,例如“2015-01-02”或我们的样本集外。
为了构建模型,我们需要为每一天和每个训练员(以及许多其他实体,但现在让我们坚持训练员)的罢工率保持一致。
我已经玩过shift 函数和数据表结构,但无法让它解决这个特定问题 - 但是,在循环上下文中它工作正常,但效果非常好。
为了说明所需的输出,这个示例代码(虽然我确信它并不优雅!)工作正常:
#order dates most recent to oldest so that the loop works backwards in time:
dt <- dt[order(-date)]
#find unique dates (converting to character as something weird with date)
dates = as.character(unique(dt$date))
for (d in dates) {
#find unique trainers on this date
trainers = unique(dt$trainer[dt$date==d])
for (t in trainers) {
trainer_past_form = dt[trainer==t & date < d]
strike_rate = sum(trainer_past_form$finish==1)/nrow(trainer_past_form)
# save this strike rate for this day and this trainer
dt$strike_rate[dt$trainer==t & dt$date==d] <- strike_rate
}
}
并给出所需的输出:
date finish trainer strike_rate
1: 2015-01-01 1 a 0.2000000
2: 2015-01-01 2 a 0.2000000
3: 2015-01-01 3 a 0.2000000
4: 2015-01-01 4 b 0.2000000
5: 2015-01-01 5 b 0.2000000
6: 2015-01-01 1 b 0.2000000
7: 2015-01-01 2 c 0.2000000
8: 2015-01-01 3 c 0.2000000
9: 2015-01-01 4 c 0.2000000
10: 2015-01-01 5 d 0.2000000
11: 2015-01-01 1 d 0.2000000
12: 2015-01-01 2 d 0.2000000
13: 2015-01-01 3 e 0.2000000
14: 2015-01-01 4 e 0.2000000
15: 2015-01-01 5 e 0.2000000
16: 2014-01-01 5 a 0.1666667
17: 2014-01-01 1 a 0.1666667
18: 2014-01-01 2 a 0.1666667
19: 2014-01-01 3 b 0.2500000
20: 2014-01-01 4 b 0.2500000
21: 2014-01-01 5 b 0.2500000
22: 2014-01-01 1 c 0.1666667
23: 2014-01-01 2 c 0.1666667
24: 2014-01-01 3 c 0.1666667
25: 2014-01-01 4 d 0.1666667
26: 2014-01-01 5 d 0.1666667
27: 2014-01-01 1 d 0.1666667
28: 2014-01-01 2 e 0.2500000
29: 2014-01-01 3 e 0.2500000
30: 2014-01-01 4 e 0.2500000
31: 2013-01-01 4 a 0.1111111
32: 2013-01-01 5 a 0.1111111
33: 2013-01-01 1 a 0.1111111
34: 2013-01-01 2 b 0.3333333
35: 2013-01-01 3 b 0.3333333
36: 2013-01-01 4 b 0.3333333
37: 2013-01-01 5 c 0.1111111
38: 2013-01-01 1 c 0.1111111
39: 2013-01-01 2 c 0.1111111
40: 2013-01-01 3 d 0.2222222
41: 2013-01-01 4 d 0.2222222
42: 2013-01-01 5 d 0.2222222
43: 2013-01-01 1 e 0.2222222
44: 2013-01-01 2 e 0.2222222
45: 2013-01-01 3 e 0.2222222
46: 2012-01-01 3 a 0.1666667
47: 2012-01-01 4 a 0.1666667
48: 2012-01-01 5 a 0.1666667
49: 2012-01-01 1 b 0.3333333
50: 2012-01-01 2 b 0.3333333
51: 2012-01-01 3 b 0.3333333
52: 2012-01-01 4 c 0.0000000
53: 2012-01-01 5 c 0.0000000
54: 2012-01-01 1 c 0.0000000
55: 2012-01-01 2 d 0.3333333
56: 2012-01-01 3 d 0.3333333
57: 2012-01-01 4 d 0.3333333
58: 2012-01-01 5 e 0.1666667
59: 2012-01-01 1 e 0.1666667
60: 2012-01-01 2 e 0.1666667
61: 2011-01-01 2 a 0.3333333
62: 2011-01-01 3 a 0.3333333
63: 2011-01-01 4 a 0.3333333
64: 2011-01-01 5 b 0.3333333
65: 2011-01-01 1 b 0.3333333
66: 2011-01-01 2 b 0.3333333
67: 2011-01-01 3 c 0.0000000
68: 2011-01-01 4 c 0.0000000
69: 2011-01-01 5 c 0.0000000
70: 2011-01-01 1 d 0.3333333
71: 2011-01-01 2 d 0.3333333
72: 2011-01-01 3 d 0.3333333
73: 2011-01-01 4 e 0.0000000
74: 2011-01-01 5 e 0.0000000
75: 2011-01-01 1 e 0.0000000
76: 2010-01-01 1 a NaN
77: 2010-01-01 2 a NaN
78: 2010-01-01 3 a NaN
79: 2010-01-01 4 b NaN
80: 2010-01-01 5 b NaN
81: 2010-01-01 1 b NaN
82: 2010-01-01 2 c NaN
83: 2010-01-01 3 c NaN
84: 2010-01-01 4 c NaN
85: 2010-01-01 5 d NaN
86: 2010-01-01 1 d NaN
87: 2010-01-01 2 d NaN
88: 2010-01-01 3 e NaN
89: 2010-01-01 4 e NaN
90: 2010-01-01 5 e NaN
任何有关在数据表中“正确”执行此操作的帮助将不胜感激。可以看出,我已经开始使用该库,但在此类问题上遇到了障碍。我了解循环的逻辑,但它在 150 万行上效率不高,需要对所有变量进行大量此类计算。
【问题讨论】:
-
那么,您需要一个针对“今天之前的数据”的罢工率,随着日期的增加而扩大?
-
是的 - 以日期为基础。因此,每一天都包含今天之前的完整历史记录(罢工率、平均值,无论计算结果如何),但没有今天本身的结果。同时,每个罢工率必须与今天的数据行一起显示,以便模型可以针对它进行训练。所示数据的示例输出是准确的,但使用缓慢的 for 循环完成。
-
如果在
for循环之前设置索引:setindex(dt, date, trainer)? -
没试过,但是很多 for 循环使它变慢所以不确定 setindex 会有什么帮助(这也是一个简化的例子,实际上我们想对骑师、马做同样的事情等)-我希望在一个语句中使用 shift 和 froll 的某种组合,但事实证明它超出了我的范围
-
如果其中一个答案解决了您的问题,请accept it;这样做不仅为回答者提供了一些积分,而且还为有类似问题的读者提供了一些关闭。尽管您只能接受一个答案,但您可以选择对您认为有帮助的人进行投票。 (如果仍有问题,您可能需要编辑您的问题并提供更多详细信息。)
标签: r loops data.table shift