【问题标题】:Creating a flag for the next hour after the last non-zero value在最后一个非零值之后的下一小时创建一个标志
【发布时间】:2020-01-27 02:25:22
【问题描述】:

我有一个带有虚拟数据的数据框:


library("lubridate")
library("dplyr")

df <- data.frame(

  time = seq.POSIXt(from = ymd_hms("2017-05-12 00:00:00"), to = ymd_hms("2017-05-12 02:25:00"), by = "5 mins"),

  value = c(rep(0, 10), 1500, 0, 1000, rep(0,17))

)

看起来像这样:


                  time value

1  2017-05-12 00:00:00     0

2  2017-05-12 00:05:00     0

3  2017-05-12 00:10:00     0

4  2017-05-12 00:15:00     0

5  2017-05-12 00:20:00     0

6  2017-05-12 00:25:00     0

7  2017-05-12 00:30:00     0

8  2017-05-12 00:35:00     0

9  2017-05-12 00:40:00     0

10 2017-05-12 00:45:00     0

11 2017-05-12 00:50:00  1500

12 2017-05-12 00:55:00     0

13 2017-05-12 01:00:00  1000

14 2017-05-12 01:05:00     0

15 2017-05-12 01:10:00     0

16 2017-05-12 01:15:00     0

17 2017-05-12 01:20:00     0

18 2017-05-12 01:25:00     0

19 2017-05-12 01:30:00     0

20 2017-05-12 01:35:00     0

21 2017-05-12 01:40:00     0

22 2017-05-12 01:45:00     0

23 2017-05-12 01:50:00     0

24 2017-05-12 01:55:00     0

25 2017-05-12 02:00:00     0

26 2017-05-12 02:05:00     0

27 2017-05-12 02:10:00     0

28 2017-05-12 02:15:00     0

29 2017-05-12 02:20:00     0

30 2017-05-12 02:25:00     0

我想创建一个标志变量来指示活动,它将包括值大于零的瞬间,以及下一个完整小时作为“1”/“开启”。

因此,如果在 00:50 有 1500 个值,那么活动应该持续到 01:50(包括 01:50)。

如果在该时间段内有另一个非零值,则活动也必须继续下一小时。

最终产品将如下所示:


                 time value flag

1  2017-05-12 00:00:00     0  OFF

2  2017-05-12 00:05:00     0  OFF

3  2017-05-12 00:10:00     0  OFF

4  2017-05-12 00:15:00     0  OFF

5  2017-05-12 00:20:00     0  OFF

6  2017-05-12 00:25:00     0  OFF

7  2017-05-12 00:30:00     0  OFF

8  2017-05-12 00:35:00     0  OFF

9  2017-05-12 00:40:00     0  OFF

10 2017-05-12 00:45:00     0  OFF

11 2017-05-12 00:50:00  1500   ON

12 2017-05-12 00:55:00     0   ON

13 2017-05-12 01:00:00  1000   ON

14 2017-05-12 01:05:00     0   ON

15 2017-05-12 01:10:00     0   ON

16 2017-05-12 01:15:00     0   ON

17 2017-05-12 01:20:00     0   ON

18 2017-05-12 01:25:00     0   ON

19 2017-05-12 01:30:00     0   ON

20 2017-05-12 01:35:00     0   ON

21 2017-05-12 01:40:00     0   ON

22 2017-05-12 01:45:00     0   ON

23 2017-05-12 01:50:00     0   ON  <-- first occurrence stops having effect

24 2017-05-12 01:55:00     0   ON  <-- effect of second occurrence

25 2017-05-12 02:00:00     0   ON  <-- continues the activity then stops

26 2017-05-12 02:05:00     0  OFF

27 2017-05-12 02:10:00     0  OFF

28 2017-05-12 02:15:00     0  OFF

29 2017-05-12 02:20:00     0  OFF

30 2017-05-12 02:25:00     0  OFF

坦率地说,我不知道如何将此任务分解为可行的 for 循环或函数。非常感谢任何帮助或线索。

更新

感谢@akrun,我有一些代码基础。但是,现在我试图确保该函数还拾取任何以下非零值,就像 1500 之后的 1000 一样,并从最后一个非零值继续活动标志,而不是第一个.

作者:阿克伦:

time                value flag 
   <dttm>              <dbl> <chr>
 1 2017-05-12 00:00:00     0 OFF  
 2 2017-05-12 00:05:00     0 OFF  
 3 2017-05-12 00:10:00     0 OFF  
 4 2017-05-12 00:15:00     0 OFF  
 5 2017-05-12 00:20:00     0 OFF  
 6 2017-05-12 00:25:00     0 OFF  
 7 2017-05-12 00:30:00     0 OFF  
 8 2017-05-12 00:35:00     0 OFF  
 9 2017-05-12 00:40:00     0 OFF  
10 2017-05-12 00:45:00     0 OFF  
11 2017-05-12 00:50:00  1500 ON   
12 2017-05-12 00:55:00     0 ON   
13 2017-05-12 01:00:00  1000 ON   
14 2017-05-12 01:05:00     0 ON   
15 2017-05-12 01:10:00     0 ON   
16 2017-05-12 01:15:00     0 ON   
17 2017-05-12 01:20:00     0 ON   
18 2017-05-12 01:25:00     0 ON   
19 2017-05-12 01:30:00     0 ON   
20 2017-05-12 01:35:00     0 ON   
21 2017-05-12 01:40:00     0 ON   
22 2017-05-12 01:45:00     0 ON   
23 2017-05-12 01:50:00     0 ON   
24 2017-05-12 01:55:00     0 OFF  <-- wrongly flagged as OFF
25 2017-05-12 02:00:00     0 OFF  <-- wrongly flagged as OFF
26 2017-05-12 02:05:00     0 OFF  
27 2017-05-12 02:10:00     0 OFF  
28 2017-05-12 02:15:00     0 OFF  
29 2017-05-12 02:20:00     0 OFF  
30 2017-05-12 02:25:00     0 OFF

【问题讨论】:

    标签: r function dataframe time-series flags


    【解决方案1】:

    我们可以根据 'value' 的出现来创建一个分组变量,该值大于cumsum

    library(dplyr)
    library(lubridate)
    df %>% 
        group_by(ind = cummax(value > 0)) %>%
       group_by(group2 =  cumsum(time >  (time[1] + hours(1))), add = TRUE) %>% 
       mutate(flag = c("OFF", "ON")[1 + (any(value > 0))]) %>% 
       ungroup %>%
       select(-ind, -group2)
    

    【讨论】:

    • 嗨,你能解释一下这段代码吗?这已经是一个很大的帮助,但是关于方法的文档有点简洁。首先,据我了解,我们使用cummax(value &gt; 0) 来查找活动的开始,但是,它不一定捕获第一个以下的任何后续值。这就是为什么它错过了 1000,并且没有包含 01:50:0001:55:00
    • @kiyanuDevs 抱歉,我没有收到您的 cmets。根据示例,它给了我预期的输出。你是说它在你的原始数据上失败了吗?
    • 我很抱歉,也许我在说明所需的输出时并不清楚。理想情况下,我希望标志拾取每个大于零的值,并将其注册为下一小时的 ON,即使存在 重叠。如果您扩展数据框,您可以看到我想要得到的结果:df &lt;- data.frame( time = seq.POSIXt(from = ymd_hms("2017-05-12 00:00:00"), to = ymd_hms("2017-05-12 04:55:00"), by = "5 mins"), value = c(rep(0, 10), 1500, 2000, rep(0,23), 1500, rep(0,24)) ) 这是问题的关键部分,因为我计划大规模应用此功能。
    【解决方案2】:

    在考虑了一段时间后,我决定尝试使用for 循环。

    这是我自己的解决方案:

    df$flag = "OFF"
    
    for (i in which(df$value != 0)) {
    
      df$flag[i:(i+12)] = "ON"
    
    }
    

    如果有人知道如何用 dplyr 的语法重新编码,你能帮忙吗?

    【讨论】:

      猜你喜欢
      • 2022-01-03
      • 2018-07-01
      • 2023-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      • 2022-01-20
      • 2014-01-08
      相关资源
      最近更新 更多