Создание флага для следующего часа после последнего ненулевого значения - PullRequest
1 голос
/ 26 сентября 2019

У меня есть фрейм данных с фиктивными данными:


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» / «on».

Итак, если в 00:50 значение 1500, то действие должно продолжаться до ивключая 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

Я, честно говоря, понятия не имею, как разбить эту задачу на выполнимый цикл или функцию.Любая помощь или подсказки высоко ценятся.

ОБНОВЛЕНИЕ

Благодаря @akrun у меня есть некоторые основы кода.Однако теперь я пытаюсь убедиться, что функция также принимает любые следующие ненулевые значения, как 1000 после 1500, и продолжает флаг активности с последнего ненулевого значения, а не с первого

от akrun:

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

Ответы [ 2 ]

0 голосов
/ 29 сентября 2019

Потратив некоторое время на обдумывание, я решил попробовать использовать цикл for.

Вот мое собственное решение:

df$flag = "OFF"

for (i in which(df$value != 0)) {

  df$flag[i:(i+12)] = "ON"

}

Если кто-нибудь знает, как это перекодироватьв синтаксисе dplyr, не могли бы вы помочь?

0 голосов
/ 26 сентября 2019

Мы можем создать группирующую переменную, основываясь на том, что значение '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)
...