R выбрать последовательность определенной длины - PullRequest
2 голосов
/ 28 марта 2019

Я пытаюсь выяснить, как выбрать последовательности длиной 3.

Рассмотрим следующую двоичную последовательность.

sq
1   0
2   0
3   0
4   1
5   1
6   0
7   0
8   1
9   1
10  1
11  1
12  0
13  0
14  0
15  1
16  1
17  0
18  1
19  1
20  1
21  1

Сначала я хотел бы определить последовательность длины 3.

Я пытался использовать:

new = sqd %>% group_by(sq) %>% mutate(sq_cum = cumsum(sq)) %>% as.data.frame()

Но это сумма всех чисел 1 в последовательности, а не подряд 1.

Мне нужен этот вектор seq_of_three.

   sq sq_cum seq_of_three
1   0      0            0
2   0      0            0
3   0      0            0
4   1      1            0
5   1      2            0
6   0      0            0
7   0      0            0
8   1      3            1
9   1      4            1
10  1      5            1
11  1      6            1
12  0      0            0
13  0      0            0
14  0      0            0
15  1      7            0
16  1      8            0
17  0      0            0
18  1      9            1
19  1     10            1
20  1     11            1
21  1     12            1

После того, как я это получу, я бы хотел установить три первые последовательности.

   sq sq_cum seq_of_three
8   1      3            1
9   1      4            1
10  1      5            1
18  1      9            1
19  1     10            1
20  1     11            1

данные

structure(list(sq = c(0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 
0, 1, 1, 0, 1, 1, 1, 1), sq_cum = c(0, 0, 0, 1, 2, 0, 0, 3, 4, 
5, 6, 0, 0, 0, 7, 8, 0, 9, 10, 11, 12), seq_of_three = c(0, 0, 
0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1)), row.names = c(NA, 
-21L), class = "data.frame")

Ответы [ 3 ]

1 голос
/ 28 марта 2019

Другая dplyr возможность может быть:

df %>%
 rowid_to_column() %>%
 group_by(grp = with(rle(sq), rep(seq_along(lengths), lengths))) %>%
 mutate(grp_seq = seq_along(grp)) %>%
 filter(sq == 1 & grp_seq %in% 1:3 & length(grp) >= 3) 

  rowid    sq   grp grp_seq
  <int> <int> <int>   <int>
1     8     1     4       1
2     9     1     4       2
3    10     1     4       3
4    18     1     8       1
5    19     1     8       2
6    20     1     8       3

Здесь он, во-первых, использует rleid() -подобную функцию для создания группирующей переменной. Во-вторых, он создает последовательность вдоль этой переменной группировки. Наконец, он сохраняет случаи, когда «sq» == 1, длина группирующей переменной равна трем или более, а последовательность вокруг группирующих переменных имеет значения от одного до трех.

1 голос
/ 28 марта 2019

Мы можем использовать rleid, чтобы создать группирующую переменную, а затем создать последовательность из трех, проверив количество строк и значения 'sq', чтобы создать двоичный столбец, filter строки, имеющие 'seq_of_three' как1, а затем slice первые 3 строки.При необходимости удалите столбец «grp»

library(dplyr)
library(data.table)
sqd %>%
  group_by(grp = rleid(sq)) %>% 
  mutate(seq_of_three =  +(n() > 3 & all(sq == 1))) %>%
  filter(seq_of_three  == 1) %>%
  slice(1:3) %>%
  ungroup %>%
  select(-grp)
# A tibble: 6 x 3
#     sq sq_cum seq_of_three
#  <dbl>  <dbl>        <int>
#1     1      3            1
#2     1      4            1
#3     1      5            1
#4     1      9            1
#5     1     10            1
#6     1     11            1

ПРИМЕЧАНИЕ. Не ясно, нужен ли нам созданный столбец seq_of_three или нет.Если нет, то шаги могут быть дополнительно сделаны компактными


Другой вариант с slice

sqd %>%
   group_by(grp = rleid(sq)) %>%
   mutate(seq_of_three =  +(n() > 3 & all(sq == 1))) %>% 
   slice(head(row_number()[seq_of_three  == 1], 3)) %>%
   ungroup %>%
   select(-grp)
0 голосов
/ 28 марта 2019
replace(ave(df1$sq, df1$sq, FUN = seq_along), df1$sq == 0, 0)
# [1]  0  0  0  1  2  0  0  3  4  5  6  0  0  0  7  8  0  9 10 11 12

with(rle(df1$sq), {
    rep(replace(rep(0, length(values)), lengths >= 3 & values == 1, 1), lengths)
})
# [1] 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1

df1[with(rle(df1$sq), {
    temp = rep(replace(rep(0, length(values)),
                       lengths >= 3 & values == 1,
                       seq(sum(lengths >= 3 & values == 1))),
               lengths)
    ave(temp, temp, FUN = seq_along) <= 3 & temp > 0
}),]
#   sq sq_cum seq_of_three
#8   1      3            1
#9   1      4            1
#10  1      5            1
#18  1      9            1
#19  1     10            1
#20  1     11            1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...