基于条件的累积和,但条件结束后会重置

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于条件的累积和,但条件结束后会重置相关的知识,希望对你有一定的参考价值。

如何在有条件的情况下提高累计和重置的性能?

我有一个data.frame,并在变量名demo下附加了一个演示数据集。我有一个带有flag的列,该列表示系统发生故障,然后是continuousfailure列,该列计算该故障连续发生了多少次,并在故障恢复后重置。我正在使用tidyverse软件包,也使用了R。

我一直在阅读有关此问题的一些StackOverflow帖子,但我似乎无法用tidyverse和/或base R更快地解决问题。我已经使用for循环实现了该版本但是对于较大的数据集,计算时间花费的时间太长(对于107388行数据帧,计算时间为9分钟)。有没有更有效的解决方案来解决这个问题?

测试数据集:

demo <- data.frame(data = rnorm(100, mean = 0, sd = 2000), flag = c(rep(FALSE, 5), rep(TRUE, 10), rep(FALSE, 25), rep(TRUE, 23), rep(FALSE, 13), rep(TRUE, 5), rep(FALSE, 19)),
continuousfailure = c(rep(0, 5), 1:10, rep(0, 25), 1:23, rep(0, 13), 1:5, rep(0, 19)),magnitude = NA)

我当前使用的代码是:

for(i in 1:length(demo$data)) {
  if(demo$flag[i]) {
    bin <- 0
    for(j in 1:demo$continuousfailure[i]) {
      bin <- bin + demo$data[i - j + 1]
    }
    demo$magnitude[i] <- bin
  }
}

[预期的输出预期是相同的,但是使用tidyverse或基数R可以提高函数的速度,通过对逻辑的构造方式进行一点解释也将不胜感激。

谢谢!

答案

我们可以使用data.table rleid创建组并根据cumsum返回NAflag

library(dplyr)

demo %>%
  group_by(group = data.table::rleid(flag)) %>%
  mutate(new_mag = if(first(flag)) cumsum(data) else NA) %>%
  ungroup %>%
  select(-group)

#     data flag  continuousfailure magnitude new_mag
#    <dbl> <lgl>             <dbl>     <dbl>   <dbl>
# 1 -1121. FALSE                 0       NA      NA 
# 2  -460. FALSE                 0       NA      NA 
# 3  3117. FALSE                 0       NA      NA 
# 4   141. FALSE                 0       NA      NA 
# 5   259. FALSE                 0       NA      NA 
# 6  3430. TRUE                  1     3430.   3430.
# 7   922. TRUE                  2     4352.   4352.
# 8 -2530. TRUE                  3     1822.   1822.
# 9 -1374. TRUE                  4      448.    448.
#10  -891. TRUE                  5     -443.   -443.
# … with 90 more rows

其中magnitude是具有for循环中的值的列,new_mag是上述代码的输出。


有多种创建组的方法。一种是如上所示,使用rleid,另一种是使用lagdplyr]中的cumsum

group_by(group = cumsum(flag != lag(flag, default = first(flag)))) %>%

和另一个带有base rle]的人>

group_by(group = with(rle(flag), rep(seq_along(lengths), lengths)))

您可以用以上任何一种替换group_by行。

数据

set.seed(123)
demo <- data.frame(data = rnorm(100, mean = 0, sd = 2000), 
flag = c(rep(FALSE, 5), rep(TRUE, 10), rep(FALSE, 25), rep(TRUE, 23),rep(FALSE, 13),
rep(TRUE, 5), rep(FALSE, 19)),continuousfailure = c(rep(0, 5), 1:10, rep(0, 25), 
1:23, rep(0, 13), 1:5, rep(0, 19)),magnitude = NA)

我们可以使用data.table方法

另一答案

我们可以使用data.table方法

以上是关于基于条件的累积和,但条件结束后会重置的主要内容,如果未能解决你的问题,请参考以下文章

Pyspark - 具有重置条件的累积和

根据条件重置的 7 天累积总和

Oracle SQL - 基于分组和条件运行求和

累积总和数据帧的条件计数 - 遍历列

带复位的累积条件乘积

pyspark中基于条件对多列进行分组的累积和函数