Finding pattern in a matrix in R

前端 未结 7 766
被撕碎了的回忆
被撕碎了的回忆 2020-12-30 04:40

I have a 8 x n matrix, for instance

set.seed(12345)
m <- matrix(sample(1:50, 800, replace=T), ncol=8)
head(m)

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8         


        
7条回答
  •  难免孤独
    2020-12-30 05:25

    This reads easily and is hopefully generalizable enough for you:

    has.37 <- rowSums(m == 37) > 0
    has.10 <- rowSums(m == 10) > 0
    has.29 <- rowSums(m == 29) > 0
    has.42 <- rowSums(m == 42) > 0
    
    lag <- function(x, lag) c(tail(x, -lag), c(rep(FALSE, lag)))
    
    which(has.37 & lag(has.10, 1) & lag(has.29, 1) & lag(has.42, 2))
    # [1] 57
    

    Edit: here is a generalization that can use positive and negative lags:

    find.combo <- function(m, pattern.df) {
    
       lag <- function(v, i) {
          if (i == 0) v else
          if (i > 0)  c(tail(v, -i), c(rep(FALSE, i))) else
          c(rep(FALSE, -i), head(v, i))
       }
    
       find.one <- function(x, i) lag(rowSums(m == x) > 0, i)
       matches  <- mapply(find.one, pattern.df$value, pattern.df$lag)
       which(rowSums(matches) == ncol(matches))
    
    }
    

    Tested here:

    pattern.df <- data.frame(value = c(40, 37, 10, 29, 42),
                             lag   = c(-1,  0,  1,  1,  2))
    
    find.combo(m, pattern.df)
    # [1] 57
    

    Edit2: following the OP's edit regarding a GUI input, here is a function that transforms the GUI input into the pattern.df my find.combo function expects:

    convert.gui.input <- function(string) {
       rows   <- strsplit(string, ";")[[1]]
       values <- strsplit(rows,   ",")
       data.frame(value = as.numeric(unlist(values)),
                  lag = rep(seq_along(values), sapply(values, length)) - 1)
    }
    

    Tested here:

    find.combo(m, convert.gui.input("37;10,29;42"))
    # [1] 57
    

提交回复
热议问题