从矩阵中拾取序列

时间:2017-12-08 13:27:20

标签: r matrix sequence

我想找到一种方法从矩阵中选择正确的"11"。 您从左上角开始[1, 1],然后从左向右移动到方向。

每当您看到组合"01""00"时,您应该继续从左向右移动,直到找到一些"11"

在示例1中,正确的解决方案是位置"11"上的[1, 3]

# Example 1:
(R) 

#       [,1] [,2] [,3]
# [1,]   01   01   11
# [2,]   11   01   11
# [3,]   01   11   10

获得"10"后,您必须更改该行并从第二行开始。 在示例2中,代码必须以"11"位置上的结果[2, 1]结束。

# Example 2:
(R1)

#       [,1] [,2] [,3]
# [1,]   01   10   11
# [2,]   11   01   11
# [3,]   01   11   10

以下命令适用于第二个示例,但不适用于第一个示例。

which(R == "11",  arr.ind = T)

我正在寻找矩阵中正确"11"的位置。任何想法都将受到高度赞赏!

P.S。 对于R和R1的复制:

R <- structure(c("01", "11", "01", "01", "01", "11", "11", "11", "10"), .Dim = c(3L, 3L))
R1 <- structure(c("01", "11", "01", "10", "01", "11", "11", "11", "10"), .Dim = c(3L, 3L))

4 个答案:

答案 0 :(得分:1)

下面是一个简单的功能,可以满足您的需求。参数是矩阵m,您要搜索的字符串strSearch(此处为“11”)以及停止搜索给定行strStop的字符串(此处为“10”)。

循环遍历每一行和每列,在找到停止字符串时断开,并在搜索字符串的第一个实例处返回。返回的长度为2的向量包含行索引和列索引。

如果找不到搜索字符串,则返回NA

R <- structure(c("01", "11", "01", "01", "01", "11", "11", "11", "10"), .Dim = c(3L, 3L))
R1 <- structure(c("01", "11", "01", "10", "01", "11", "11", "11", "10"), .Dim = c(3L, 3L))

getPosition <- function(m, strSearch, strStop) {

  for (i in seq_len(nrow(m))) {
    for (j in seq_len(ncol(m))) {
      if (m[i, j] == strStop) break
      if (m[i, j] == strSearch) return(c(i, j))
    }
  }

  return(NA)
}

示例输出:

> getPosition(R, "11", "10")
[1] 1 3
> getPosition(R1, "11", "10")
[1] 2 1

答案 1 :(得分:1)

这有效:

find_index <- function(matr) {
  # find the col index of first "10" in each row 
  ind10 <- apply(matr, 1, function(x) ifelse(sum(x == "10") == 0, 
                 length(x) + 1, min(seq_len(length(x))[x == "10"])))
  # find the col index of first "11" in each row 
  ind11 <- apply(matr, 1, function(x) ifelse(sum(x == "11") == 0, 
                 length(x) + 1, min(seq_len(length(x))[x == "11"])))

  # check if 11 is before 10
  ind <- ifelse(ind10 < ind11, NA, ind11)

  # select the first row where "11" is before "10"
  rownumber <- which(!is.na(ind))[1]
  # and its colnumber
  colnumber <- ind[rownumber]
  return(c(rownumber, colnumber))
}
find_index(R)
find_index(R1)

然后输出是这样的。

> find_index(R)
[1] 1 3
> find_index(R1)
[1] 2 1
> 

由于您没有指定如果存在“11”,“01”,“10”,“00”以外的条目会发生什么,我忽略了这种可能性。

修改 由于阅读起来很复杂,我创建了一个带有文本连接的可读版本。

library(stringi)
library(dplyr)

find_11_before_10 <- function(x){
  text <- x %>% paste(collapse = "|") 
  if(stri_detect_fixed(text, "11") &
     stri_detect_regex(text, "10.+11", negate = T)){
    return(which(x == "11") %>% min)
  } else {
    return(NA)
  }
}

find_index2 <- function(matr){
  ind <- apply(matr, 1, find_11_before_10)
  rownumber <- which(!is.na(ind))[1]
  colnumber <- ind[rownumber]
  return(c(rownumber, colnumber))
}

find_index2(R)
find_index2(R1)

答案 2 :(得分:1)

以下是两种方法。

1)正则表达式t(m)折叠到一个以空格分隔的字符串中,并使用带有指定正则表达式的strapply来挑选从该字符串开头到第一个11跟随00或01.提取的字符串中的空格数加1是11的位置。将其转换为行号和列号。

library(gsubfn)

v <- paste(t(m), collapse = " ")
ix <- head(strapply(v, ".*?0[01].*?11", ~ nchar(gsub("\\S", "", x)), simplify = c), 1) + 1
c(t(row(m))[ix], t(col(m))[ix])
## [1] 1 3

2)位置/查找另一种方法计算第一个00或01,w0ix的位置,前11个的位置大于{ {1}}。最后 计算行号和列号。

w0

3)状态机使用switch和Reduce可以实现状态机。我们在州1开始。一旦我们找到00或01,我们转换到状态2,当在状态2时,我们转换到状态3.如果我们处于状态3或4,我们转换到状态4.状态3是状态3在00或01之后的第11个。

w0 <- Position(isTRUE, grepl("0[01]", t(m)))
ix <- Find(function(x) x > w0, which(t(m) == 11))
c(t(row(m))[ix], t(col(m))[ix])
    ## [1] 1 3

注意:我们将此作为输入:

transition <- function(state, x)
  switch(state,
    if (x == "00" || x == "01") 2 else 1,
    if (x == "11") 3 else 2,
    4,
    4)
r <- Reduce(transition, init = 1, c(t(m)), accumulate = TRUE)[-1]
ix <- which(r == 3)
c(t(row(m))[ix], t(col(m))[ix])
## [1] 1 3

答案 3 :(得分:1)

这是另一个为你做的小功能:

foo <- function(mat, a, b) {
  res <- t(apply(mat, 1, function(x) replace(x, cumsum(x == a) > 0, NA)))
  res <- which(res == b, arr.ind = TRUE)
  res[order(res[,1], res[,2]),][1,]
}

foo(R, "10", "11")
#row col 
#  1   3 
foo(R1, "10", "11")
#row col 
#  2   1 

这是按行进行的,用“NA”替换NA之后的所有元素,然后得到第一个“11”出现。