我想使用数据表计算滚动分位数,数据表包含多个组的数据,对于每组我有多天,每天我有多个观察。我不想计算表格中每个观察点的滚动分位数,但总是记录最后一天的数据,比如3天,计算分位数并继续前进。
我有这样的数据:
test2 <- data.table(group = rep(c("a", "b"), each = 100),
date = rep(rep(seq(from = as.Date('2017-01-01'),
as.Date('2017-01-10'),
by = "day"), each = 10), 2),
time = rep(rep(seq(from = 1, 10, by = 1), times = 10), 2),
some_data = rnorm(200) + c(1:20, 20:1, 30:1, 1:30, 30:1, 1:20, 20:1, 1:30))
上表有2个不同的组,每组有10天的数据,每天有10个观察值。接下来,我想计算每个组的滚动分位数。
理论上,我可以像这样计算:
tests_result <- test2[, list(date = date,
q_30 = rollapply(some_data,
30, quantile,
probs = 0.3,
fill = NA, align = "right")),
by = "group"][seq(from = 10, to = 200, by = 10)]
但即使我使用基于c ++的代码计算分位数,这也会非常缓慢!所以我真正想要的是仅将结果返回到当天的最后一次观察。
问题2)我每天都有不同数量的观测值,但仍希望能够计算特定天数的滚动分位数(而不是设置评估分位数的窗口的固定宽度)
示例方案中的输出应如下所示:
group date q_30
1: a 2017-01-01 NA
2: a 2017-01-02 NA
3: a 2017-01-03 10.284081
4: a 2017-01-04 8.281827
5: a 2017-01-05 8.281827
6: a 2017-01-06 8.281827
7: a 2017-01-07 10.274793
8: a 2017-01-08 4.749455
9: a 2017-01-09 4.749455
10: a 2017-01-10 9.246267
11: b 2017-01-01 NA
12: b 2017-01-02 NA
13: b 2017-01-03 10.145996
14: b 2017-01-04 5.423782
15: b 2017-01-05 5.423782
16: b 2017-01-06 9.741683
17: b 2017-01-07 10.123940
18: b 2017-01-08 4.347293
19: b 2017-01-09 4.347293
20: b 2017-01-10 9.177718
总结挑战:
修改
我想办法如何处理我拥有的数据集。但我认为它仍然有很大的改进,所以,如果你有任何建议,我想听听它们。
我对样本数据集的处理方式如下:
首先计算每个后续3天的观测总数,同时计算给定日期最后一次观测的原始数据集中的行数。这些新变量将被称为in_3
和orig_row
。
test3 <- test2[, list(.N, orig_row = .I[.N]), by = c("group", "date")][, list(date,in_3 = rollapply(N, 3, sum, fill = NA, align = "right"),
orig_row),
by = "group"]
然后使用foreach
包迭代原始数据帧的相关子集并计算每个子集的分位数。
library(foreach)
quantiles <- foreach(i = 1:nrow(test3),.combine = 'c') %do%
ifelse(!is.na(test3[i]$V3 - test3[i]$in_3 + 1),
test2[(test3[i]$orig_row - 3[i]$in_3 + 1):test3[i]$orig_row][,quantile(some_data, probs = 0.3)],
NA)
最后,分配到聚合数据集
test3[, `:=`(q03 = quantiles)]
我也尝试并行运行它,但是我的笔记本电脑耗尽了物理内存并且开始写入磁盘太多了,这使得进程减慢得更多,然后只用一个核心进行运算。