如何解决达到阈值时,dplyr重置计数器
我有以下称为tibble
的{{1}}:
test
我想计算达到 datetime volume
<dttm> <dbl>
2020-08-25 09:30:00.000 0
2020-08-25 09:30:12.000 107
2020-08-25 09:30:50.000 221
2020-08-25 09:30:50.000 132
2020-08-25 09:30:50.000 148
2020-08-25 09:30:50.000 100
2020-08-25 09:30:50.000 100
2020-08-25 09:30:58.000 100
2020-08-25 09:31:56.000 157
2020-08-25 09:32:36.000 288
2020-08-25 09:32:36.000 100
2020-08-25 09:33:10.000 235
2020-08-25 09:33:23.000 182
2020-08-25 09:33:44.000 218
2020-08-25 09:33:44.000 179
2020-08-25 09:34:18.000 318
2020-08-25 09:34:27.000 101
2020-08-25 09:34:27.000 157
2020-08-25 09:34:27.000 200
2020-08-25 09:34:27.000 114
的阈值时的累积时间差(或什至只是时间戳相同的行数)。达到/超过阈值后,我将计数器重置为0,然后再次从该点开始累积。
例如,如果我的volume
是300,则从行threshold
到行1
累积,我得到3
,我现在选择: / p>
- 保留该行的时间戳,
- 计算从第
0+107+221=328
行到第1
行的时间差, - 或计算直到达到阈值为止的行数
以上任何一项都可以达到目的,最好的选择是保留时间戳。
下一步是重置计数器(当前停留在3
处),并从行328
开始重新计数;从第4
行到第4
行,我累积了7
,我将再次保留时间戳记(例如)。然后,我再次重置计数器,然后再次继续。
我尝试使用148+100+100=348
或通常在dplyr
中进行此操作,但是我无法提出合理的解决方案。我认为没有办法仅将管道与dplyr一起使用。
我认为我可以接受tidyverse
,但这是我的最后选择。对我来说,最困难的部分是重置计数器并重新开始计数。
解决方法
一种dplyr
和purrr
的可能性是:
df %>%
group_by(group_id = cumsum(c(0,diff(accumulate(volume,~ if_else(.x >= 300,.y,.x + .y))) < 0))) %>%
summarise(timestamp_first = first(datetime),timestamp_last = last(datetime),time_diff = last(datetime) - first(datetime),n_rows = n(),volume_sum = sum(volume))
group_id timestamp_first timestamp_last time_diff n_rows volume_sum
<dbl> <dttm> <dttm> <drtn> <int> <int>
1 0 2020-08-25 09:30:00 2020-08-25 09:30:50 50 secs 3 328
2 1 2020-08-25 09:30:50 2020-08-25 09:30:50 0 secs 3 380
3 2 2020-08-25 09:30:50 2020-08-25 09:31:56 66 secs 3 357
4 3 2020-08-25 09:32:36 2020-08-25 09:32:36 0 secs 2 388
5 4 2020-08-25 09:33:10 2020-08-25 09:33:23 13 secs 2 417
6 5 2020-08-25 09:33:44 2020-08-25 09:33:44 0 secs 2 397
7 6 2020-08-25 09:34:18 2020-08-25 09:34:18 0 secs 1 318
8 7 2020-08-25 09:34:27 2020-08-25 09:34:27 0 secs 3 458
9 8 2020-08-25 09:34:27 2020-08-25 09:34:27 0 secs 1 114
,
这可能会让您前进。它利用MESS
包,尤其是天才cumsumbinning
函数。
样本数据
library( data.table )
library( MESS )
test <- data.table::fread( "datetime volume
2020-08-25T09:30:00.000 0
2020-08-25T09:30:12.000 107
2020-08-25T09:30:50.000 221
2020-08-25T09:30:50.000 132
2020-08-25T09:30:50.000 148
2020-08-25T09:30:50.000 100
2020-08-25T09:30:50.000 100
2020-08-25T09:30:58.000 100
2020-08-25T09:31:56.000 157
2020-08-25T09:32:36.000 288
2020-08-25T09:32:36.000 100
2020-08-25T09:33:10.000 235
2020-08-25T09:33:23.000 182
2020-08-25T09:33:44.000 218
2020-08-25T09:33:44.000 179
2020-08-25T09:34:18.000 318
2020-08-25T09:34:27.000 101
2020-08-25T09:34:27.000 157
2020-08-25T09:34:27.000 200
2020-08-25T09:34:27.000 114")
test[,datetime := as.POSIXct( datetime,format = "%Y-%m-%dT%H:%M:%OS") ]
代码
采用data.table
语法,但可以很容易地集成到任何tidyverse或baseR解决方案中
#create groups based on cumsum with threshold of 300
test[,group_id := MESS::cumsumbinning( volume,threshold = 300,cutwhenpassed = TRUE )]
# datetime volume group_id
# 1: 2020-08-25 09:30:00 0 1
# 2: 2020-08-25 09:30:12 107 1
# 3: 2020-08-25 09:30:50 221 1
# 4: 2020-08-25 09:30:50 132 2
# 5: 2020-08-25 09:30:50 148 2
# 6: 2020-08-25 09:30:50 100 2
# 7: 2020-08-25 09:30:50 100 3
# 8: 2020-08-25 09:30:58 100 3
# 9: 2020-08-25 09:31:56 157 3
# 10: 2020-08-25 09:32:36 288 4
# 11: 2020-08-25 09:32:36 100 4
# 12: 2020-08-25 09:33:10 235 5
# 13: 2020-08-25 09:33:23 182 5
# 14: 2020-08-25 09:33:44 218 6
# 15: 2020-08-25 09:33:44 179 6
# 16: 2020-08-25 09:34:18 318 7
# 17: 2020-08-25 09:34:27 101 8
# 18: 2020-08-25 09:34:27 157 8
# 19: 2020-08-25 09:34:27 200 8
# 20: 2020-08-25 09:34:27 114 9
现在分组完成了,总结应该很容易。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。