R选择一定长度的序列

时间:2019-03-28 19:08:16

标签: r

我正在尝试找出如何选择长度为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 个答案:

答案 0 :(得分:1)

我们可以使用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)

答案 1 :(得分:1)

另一种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到3。

答案 2 :(得分:0)

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