2017-01-04 8 views
2

Модифицированные данные:накопленная сумма игнорируя разрывы

structure(list(hour = c(0L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 0L, 
1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 1L, 1L, 1L, 0L, 1L, 1L, 0L, 0L), cs = c(0L, 0L, 0L, 0L, 
0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 
1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 0L, 0L 
), cs_acum = c(0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 1L, 2L, 0L, 0L), cs_wanted = c(0L, 0L, 0L, 0L, 
0L, 1L, 2L, 3L, 0L, 0L, 4L, 5L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 
3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 0L, 0L 
), cs_acum2 = c(0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 4L, 5L, 
0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
1L, 2L, 3L, 0L, 4L, 5L, 0L, 0L)), .Names = c("hour", "cs", "cs_acum", 
"cs_wanted", "cs_acum2"), class = c("data.table", "data.frame" 
), row.names = c(NA, -36L), .internal.selfref = <pointer: 0x00000000001f0788>) 

cs_acum является накопленная сумма cs с рестарта в 0.

df1$cs_acum <- with(df1, ave(df1$cs, cumsum(df1$cs == 0), FUN = cumsum)) 

мне нужно это накопление, чтобы продолжать, если есть значение 1 в 5 строк от hourпосле накопления 1 с cs остановился.
Желаемый выход в колонке cs_wanted.

Дополнительные пояснения: çs_acum - это накопление часов (строки f cs), которые отвечают определенным критериям. После этого он больше не связан с cs, тогда он связан с col: hour. Накопление должно продолжаться, если после его остановки будет отображаться значение 1 в 5-часовом окне.

Возможно новая функция проверки пять строк в hour из положения в cs_acum превращается в 0, все будет в порядке, продолжая накопление, откуда он остановился в cs_acum.
Возможных шаги:
положения находки, где накопление останавливается
взгляд на следующие пять строк в часе
если есть значения 1, продолжают накопление для этой линии,
посмотреть еще раз в течение пяти часов,
, если есть нет значений 1, ничего не делать.


Новые данные:

df3 <- structure(list(hour = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
         cs = c(0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
         cs_acum = c(0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), 
         cs_acum2 = c(0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 8, 9, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28)), 
       .Names = c("hour", "cs", "cs_acum", "cs_acum2"), class = "data.frame", row.names = c(NA, -68L)) 
+0

Я действительно не знаю, как объяснить это лучше. См. Пример накопления в cs_wanted, и это должно быть ясно. если нет, я дам ему еще один шаг. –

+0

Нет, мне нужны часы, соответствующие определенным критериям. –

ответ

1

Мы можем попробовать это с помощью только data.table методы

library(data.table) 
setDT(df1)[, grp := shift(cumsum(hour == 1 & (Reduce(`+`, 
    shift(hour, 1:5, fill = 1, type = "lead"))==0)), fill=0) 
    ][hour ==1, cs_acum1 := cumsum(hour) , grp 
     ][is.na(cs_acum1), cs_acum1 := 0][, grp := NULL][] 
#  hour cs cs_acum cs_wanted cs_acum1 
# 1: 1 1  1   1  1 
# 2: 1 1  2   2  2 
# 3: 1 1  3   3  3 
# 4: 0 0  0   0  0 
# 5: 0 0  0   0  0 
# 6: 1 0  0   4  4 
# 7: 1 0  0   5  5 
# 8: 0 0  0   0  0 
# 9: 0 0  0   0  0 
#10: 0 0  0   0  0 
#11: 0 0  0   0  0 
#12: 0 0  0   0  0 
#13: 0 0  0   0  0 
#14: 1 1  1   1  1 
#15: 1 1  2   2  2 
#16: 1 1  3   3  3 
#17: 0 0  0   0  0 

Объяснение

Превратим «data.frame 'to' data.tabl e '(setDT(df1)), создайте переменную группировки с использованием значений «часа» lead, чтобы создать условие в сообщении OP, укажите «i» (hour==1), сгруппированные по «grp», и назначьте (:=) cumsum из часа 'как 'cs_acum1', изменить элементы NA Ито 0 и, наконец, удалить 'GRP', назначив ее NULL

+3

Я не понимаю, как этот дублированный вопрос о том, с кем вы связались? –

+0

Мне удалось запустить его на более широком наборе, обнаружив, что он не дает мне то, что я хочу. Мне нужно, чтобы накопление продолжалось, только если оно уже началось в 'cs_acum' –

+0

@m_c Спасибо за обновление. Я вижу, как другой плакат много работает над каждым из ваших обновлений. Итак, я не хочу испортить его усилия :-) – akrun

6

Использование:

library(data.table) 

rl <- rle(df1$hour) 

setDT(df1)[, grp := rleid(rep(rl$lengths >5 & rl$values == 0, rl$lengths)) 
      ][hour == 1, cs_acum2 := cumsum(hour), grp 
      ][is.na(cs_acum2), cs_acum2 := 0][] 

дает:

hour cs cs_acum cs_wanted grp cs_acum2 
1: 1 1  1   1 1  1 
2: 1 1  2   2 1  2 
3: 1 1  3   3 1  3 
4: 0 0  0   0 1  0 
5: 0 0  0   0 1  0 
6: 1 0  0   4 1  4 
7: 1 0  0   5 1  5 
8: 0 0  0   0 2  0 
9: 0 0  0   0 2  0 
10: 0 0  0   0 2  0 
11: 0 0  0   0 2  0 
12: 0 0  0   0 2  0 
13: 0 0  0   0 2  0 
14: 1 1  1   1 3  1 
15: 1 1  2   2 3  2 
16: 1 1  3   3 3  3 
17: 0 0  0   0 3  0 

Объяснение:

  • Преобразование данных в формат данных с setDT(df1).
  • С rl <- rle(d1$hour) и grp := rleid(rep(rl$lengths >5 & rl$values == 0, rl$lengths)) вы создаете переменную группировки, которая изменяется только при наличии более 5 нулей.
  • Далее вы фильтруете по hour == 1 и создадите совокупную сумму с cumsum(hour). Если ваши значения в hour являются только 1 и 0, вы также можете создать счетчик с seq_along или 1:.N, который даст тот же результат.
  • Наконец, с is.na(cs_acum2), cs_acum2 := 0 вы меняете NA на ноль.

Обновление 1: Для новых примера данных (df2):

rl2 <- rle(df2$hour) 

setDT(df2)[, `:=` (rn = .I, grp = rleid(rep(rl2$lengths >5 & rl2$values == 0, rl2$lengths))) 
      ][hour == 1 & rn >= df2[, .I[cs == 1]][1], cs_acum2 := cumsum(hour), grp 
      ][is.na(cs_acum2), cs_acum2 := 0][, c('rn','grp') := NULL][] 

который дает:

hour cs cs_acum cs_wanted cs_acum2 
1: 0 0  0   0  0 
2: 1 0  0   0  0 
3: 1 0  0   0  0 
4: 1 0  0   0  0 
5: 0 0  0   0  0 
6: 1 1  1   1  1 
7: 1 1  2   2  2 
8: 1 1  3   3  3 
9: 0 0  0   0  0 
10: 0 0  0   0  0 
11: 1 0  0   4  4 
12: 1 0  0   5  5 
13: 0 0  0   0  0 
14: 0 0  0   0  0 
15: 0 0  0   0  0 
16: 0 0  0   0  0 
17: 0 0  0   0  0 
18: 0 0  0   0  0 
19: 1 1  1   1  1 
20: 1 1  2   2  2 
21: 1 1  3   3  3 
22: 0 0  0   0  0 

так, как я понял это, что cumsum из hour разрешено начинать только после первого появления cs == 1.

Дополнительное объяснение:

  • С rn = .I вы в rowindexnumber создающих.
  • df2[, .I[cs == 1]][1] дать вам номер рулона, где cs == 1 в первый раз.
  • С помощью rn >= df2[, .I[cs == 1]][1] вы выбираете только строки из этой точки вперед.

Update 2: Что касается последнего (четвертого) набора данных, вы можете сделать:

rl4 <- rle(df4$hour) 

setDT(df4)[, grp := rleid(rep(rl4$lengths >5 & rl4$values == 0, rl4$lengths))] 

i1 <- df4[, .I[cs == 1][1], grp][!is.na(V1)]$V1 
i2 <- df4[, .I[1:.N==5], rleid(cs)]$V1[-1] + 1 

df4[i1, cs.inc := 1 
    ][i2, cs.inc := -1 
     ][is.na(cs.inc), cs.inc := 0 
     ][, cs.inc := cumsum(cs.inc) 
      ][hour == 1 & cs.inc == 1, cs_acum3 := cumsum(hour), grp 
      ][is.na(cs_acum3), cs_acum3 := 0][, c('grp','cs.inc') := NULL][] 

, который дает:

hour cs cs_acum cs_wanted cs_acum2 cs_acum3 
1: 0 0  0   0  0  0 
2: 1 0  0   0  0  0 
3: 1 0  0   0  0  0 
4: 1 0  0   0  0  0 
5: 0 0  0   0  0  0 
6: 1 1  1   1  1  1 
7: 1 1  2   2  2  2 
8: 1 1  3   3  3  3 
9: 0 0  0   0  0  0 
10: 0 0  0   0  0  0 
11: 1 0  0   4  4  4 
12: 1 0  0   5  5  5 
13: 0 0  0   0  0  0 
14: 0 0  0   0  0  0 
15: 0 0  0   0  0  0 
16: 0 0  0   0  0  0 
17: 0 0  0   0  0  0 
18: 0 0  0   0  0  0 
19: 1 1  1   1  1  1 
20: 1 1  2   2  2  2 
21: 1 1  3   3  3  3 
22: 0 0  0   0  0  0 
23: 0 0  0   0  0  0 
24: 0 0  0   0  0  0 
25: 0 0  0   0  0  0 
26: 0 0  0   0  0  0 
27: 0 0  0   0  0  0 
28: 0 0  0   0  0  0 
29: 1 0  0   0  1  0 
30: 1 0  0   0  2  0 
31: 1 0  0   0  3  0 
32: 0 0  0   0  0  0 
33: 1 1  1   1  4  1 
34: 1 1  2   2  5  2 
35: 0 0  0   0  0  0 
36: 0 0  0   0  0  0 

Б данные

Первый пример набора данных:

df1 <- structure(list(hour = c(1L, 1L, 1L, 0L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L), 
         cs = c(1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L), 
         cs_acum = c(1L, 2L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L), 
         cs_wanted = c(1L, 2L, 3L, 0L, 0L, 4L, 5L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L)), 
       .Names = c("hour", "cs", "cs_acum", "cs_wanted"), class = "data.frame", row.names = c(NA, -17L)) 

Второй набор данных:

df2 <- structure(list(hour = c(0L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L), 
         cs = c(0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L), 
         cs_acum = c(0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L), 
         cs_wanted = c(0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 4L, 5L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L)), 
       .Names = c("hour", "cs", "cs_acum", "cs_wanted"), class = "data.frame", row.names = c(NA, -22L)) 

Четвертый набор данных:

df4 <- structure(list(hour = c(0L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 1L, 1L, 0L, 0L), 
         cs = c(0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 1L, 0L, 0L), 
         cs_acum = c(0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 0L, 0L), 
         cs_wanted = c(0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 4L, 5L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 0L, 0L), 
         cs_acum2 = c(0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 4L, 5L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 4L, 5L, 0L, 0L)), 
       .Names = c("hour", "cs", "cs_acum", "cs_wanted", "cs_acum2"), class = "data.frame", row.names = c(NA, -36L)) 
+0

такая же проблема возникает в этом наборе данных, но посмотрите на строку 48. –

+0

см. Измененный набор данных, скопление в строке 29, после запуска вашего кода –

+0

Я боюсь, что снова у нас та же проблема. Он не может использоваться для других наборов данных. Большое спасибо за усилия. –