3
mydf <- tibble::tribble(
   ~seq, ~flag,
      0,     0,
      0,     0,
      0,     0,
      1,     1,
      1,     1,
      7,     1,
      1,     1,
      3,     1,
      2,     1,
      1,     1,
      1,     1,
      0,     1,
      0,     1,
      0,     0,
      0,     0,
      1,     1,
      1,     1,
      7,     1,
      1,     1,
      3,     1,
      2,     1,
      1,     1,
      1,     1,
      0,     1,
      0,     1,
      0,     0,
      0,     0,
      2,     0
)

I have a dataframe with a sequence column. How can I create a binary flag to mark any particular number sequence? My example sequence is 1, 1, 7, 1, 3, 2, 1, 1, 0, 0.

Eugene
  • 55
  • 6
  • Not an exact duplicate but take a look at [this question](https://stackoverflow.com/questions/31439273/r-identify-consecutive-sequences). – Rui Barradas Feb 26 '19 at 12:17
  • 1
    Maybe treat seq column as one string `paste(mydf$seq, collapse = ",")`, then use grep? – zx8754 Feb 26 '19 at 12:27

2 Answers2

2
library(zoo)
match_seq <- c(1, 1, 7, 1, 3, 2, 1, 1, 0, 0)
is_start <- rollapply(mydf$seq, length(match_seq), function(x) all(x == match_seq))
inds <- sapply(which(is_start), `+`, seq_along(match_seq) - 1)

mydf$flag2 <- as.numeric(1:nrow(mydf) %in% inds)


#    seq flag flag2
# 1    0    0     0
# 2    0    0     0
# 3    0    0     0
# 4    1    1     1
# 5    1    1     1
# 6    7    1     1
# 7    1    1     1
# 8    3    1     1
# 9    2    1     1
# 10   1    1     1
# 11   1    1     1
# 12   0    1     1
# 13   0    1     1
# 14   0    0     0
# 15   0    0     0
# 16   1    1     1
# 17   1    1     1
# 18   7    1     1
# 19   1    1     1
# 20   3    1     1
# 21   2    1     1
# 22   1    1     1
# 23   1    1     1
# 24   0    1     1
# 25   0    1     1
# 26   0    0     0
# 27   0    0     0
# 28   2    0     0

One way to calculate is_start without library(zoo) is

subseqs <- 
  sapply(seq(0, nrow(mydf) - length(match_seq)), 
         function(i) mydf$seq[i + seq_along(match_seq)])

is_start <- colMeans(subseqs == match_seq) == 1
IceCreamToucan
  • 28,083
  • 2
  • 22
  • 38
1

A solution using tidyverse.

library(tidyverse)

st <- str_c(mydf$seq, collapse = "")

pos <- str_locate_all(st, "1171321100")

index <- map2(pos[[1]][, 1], pos[[1]][, 2], `:`) %>% unlist()


mydf2 <- mydf %>%
  mutate(Result = as.integer(row_number() %in% index))
mydf2
# # A tibble: 28 x 3
#     seq  flag Result
#    <dbl> <dbl>  <int>
#  1     0     0      0 
#  2     0     0      0
#  3     0     0      0
#  4     1     1      1
#  5     1     1      1
#  6     7     1      1
#  7     1     1      1
#  8     3     1      1
#  9     2     1      1
# 10     1     1      1
# # ... with 18 more rows
www
  • 38,575
  • 12
  • 48
  • 84
  • 1
    Assuming `seq` is a single digit columns. – zx8754 Feb 26 '19 at 12:32
  • @zx8754 Good. My solution can only work for single digit columns. More advanced or generalized are welcomed. – www Feb 26 '19 at 12:38
  • @zx8754 One idea is to use `str_pad` to add leading `0` if both signle or double (or more) digits exist, and then apply the same strategy, but it will dependes on if the OP needs it. If that is the case, I welcome OP to post an other example and I will update my post when I have time. – www Feb 26 '19 at 12:41
  • I had a similar solution in mind with `collapse = ","` in the comments, hence commented as a "warning". Agree OP needs to clarify input. – zx8754 Feb 26 '19 at 13:05