【问题标题】:Find array index of elements of a matrix that match a value in a vector of candidate values查找与候选值向量中的值匹配的矩阵元素的数组索引
【发布时间】:2020-01-13 11:00:46
【问题描述】:

我已经在谷歌上搜索和堆栈溢出了一段时间,但我似乎找不到正确的答案。

我有一个矩阵,其中包含不同的字符串,例如"a""gamma",甚至是强制转换为字符的数字。

如果m 的元素与候选值向量中的值匹配,我如何获取矩阵m 的数组索引(请注意,这些值可以是任何字符串)。这是我尝试过的。我虽然 which(m %in% ...) 会这样做,但它并没有返回我的预期。

m <- matrix(c(0, "a", "gamma", 0, 0.5, 0, 0, 0, 0), ncol = 3)
m
#>      [,1]    [,2]  [,3]
#> [1,] "0"     "0"   "0" 
#> [2,] "a"     "0.5" "0" 
#> [3,] "gamma" "0"   "0"

which(m == "a", arr.ind = TRUE) # as expected
#>      row col
#> [1,]   2   1

which(m == "a" | m == "gamma", arr.ind = TRUE) # also obvious
#>      row col
#> [1,]   2   1
#> [2,]   3   1

candidates <- c("a", "gamma", "b")
which(m %in% candidates, arr.ind = TRUE) # not what I expected
#> [1] 2 3

reprex package (v0.3.0) 于 2019 年 9 月 11 日创建

  • 我想要的结果是m中元素的行列索引 匹配candiates 中的值。
  • 如果可能,我更喜欢基础 R 解决方案。

有什么帮助吗?

【问题讨论】:

    标签: r matrix subset


    【解决方案1】:

    以下函数是%in% 的变体,其行为与== 更加一致,这包括矩阵行为,也包括其他类,它确保NA 保持NA。

    `%in{}%` <- function(x, table) {
      table <- unlist(table)
      if (is.list(x) && !is.data.frame(x)) {
        x <- switch(
          typeof(table),
          logical = as.logical(x),
          integer = as.integer(x),
          double = as.double(x),
          complex = as.complex(x),
          character = as.character(x),
          raw = as.raw(x))
      }
    
      # convert to character
      if (is.factor(table)) {
        table <- levels(table)[table]
      }
      if (is.data.frame(x)){
          res <- sapply(x, `%in%`, table)
        } else if (is.matrix(x)){
        res <- apply(x, 2, `%in%`, table)
      } else {
        res <- x %in% table
      }
      res[is.na(x)] <- NA
      res
    }
    
    m <- matrix(c(0, "a", "gamma", 0, 0.5, 0, 0, 0, 0), ncol = 3)
    candidates <- c("a", "gamma", "b")
    which(m %in{}% candidates, arr.ind = TRUE)
    #>      row col
    #> [1,]   2   1
    #> [2,]   3   1
    

    【讨论】:

      【解决方案2】:

      MrFlick 的解决方案可能是你能得到的最好的解决方案之一,但如果你必须坚持使用基础 R 中的内置函数,这里有一种方法 -

      which(matrix(m %in% candidates, dim(m)), arr.ind = T)
      
           row col
      [1,]   2   1
      [2,]   3   1
      

      lapplyReduce 的另一种方式,但上面应该更快 -

      which(Reduce("|", lapply(candidates, function(x) m == x)), arr.ind = T)
      
           row col
      [1,]   2   1
      [2,]   3   1
      

      【讨论】:

      • 我喜欢第一个解决方案。直截了当和基本的R-ish。谢谢
      • @ManuelR 谢谢,但老实说,MrFlick 的解决方案也是基于 R 的。您可以使用 '%matin%' &lt;- function(x, table) { stopifnot(is.array(x)) matrix(x %in% table, dim(x)) } 将他的优雅与我的代码结合起来
      【解决方案3】:

      问题在于%in% 不保留输入的尺寸。您可以编写自己的函数来做到这一点。例如

      `%matin%` <- function(x, table) {
        stopifnot(is.array(x))
        r <- x %in% table
        dim(r) <- dim(x)
        r
      }
      
      candidates <- c("a", "gamma", "b")
      which(m %matin% candidates, arr.ind = TRUE)
      #      row col
      # [1,]   2   1
      # [2,]   3   1
      

      【讨论】:

      • 好的,这对我有用。我假设您也不知道有一个“即用型”基本 R 函数可以做到这一点?
      猜你喜欢
      • 1970-01-01
      • 2015-05-13
      • 2015-07-29
      • 2017-11-26
      • 2013-01-03
      • 1970-01-01
      • 2019-12-10
      • 2021-11-03
      • 2016-03-21
      相关资源
      最近更新 更多