【问题标题】:How to find the location (row/column) of the minimum/maximum value of a data frame or a matrix (R question)如何找到数据框或矩阵的最小值/最大值的位置(行/列)(R问题)
【发布时间】:2020-02-22 06:25:27
【问题描述】:

我想找到数据框或矩阵的最小值或最大值的位置。

例如,让我使用最小值矩阵的例子(我们暂时不考虑相同值的存在):

B<-matrix(c(1.5,2,3,4,5,5,4,3,2,1,2,4,6,8,10),nrow=3,ncol=5)
B
     [,1] [,2] [,3] [,4] [,5]
[1,]   1.5    4    4    1    6
[2,]    2    5    3    2    8
[3,]    3    5    2    4   10

我想要的输出是:

row.number = 1

column.number = 4

我试过 which.min 或 which.max。它只返回“总”位置,就好像输入是一个向量(它将返回单个数字 4)

提前致谢!

【问题讨论】:

    标签: r matrix data-manipulation


    【解决方案1】:

    虽然which.min 和朋友不直接支持这一点,但which(..., arr.ind=TRUE) 支持:

    which(B == min(B), arr.ind=TRUE)
    #      row col
    # [1,]   1   4
    

    非常重要旁注:这样做有两个注意事项:

    1. 这不报告存在关系;和

    2. 这假设浮点相等会起作用,这很容易出现Why are these numbers not equal?R FAQ 7.31。因此,虽然这可能在大多数情况下都有效,但它并不总是有效。可行。在它不起作用的情况下,它将返回一个 0-row matrix。一个缓解步骤是引入容差,例如

      which(abs(B - min(B)) < 1e-9, arr.ind=TRUE)
      #      row col
      # [1,]   1   4
      

      其中1e-9 故意很小,但“小”是相对于矩阵中预期值的范围而言的。

    更快的选择

    老实说,which.max 给了你足够的信息,因为你知道矩阵的维度。

    m <- which.min(B)
    c( (m-1) %% nrow(B) + 1, (m-1) %/% nrow(B) + 1 )
    # [1] 1 4
    

    对于背景,R 中的 matrix 只是一个向量,按列排序。

    matrix(1:15, nrow=3)
    #      [,1] [,2] [,3] [,4] [,5]
    # [1,]    1    4    7   10   13
    # [2,]    2    5    8   11   14
    # [3,]    3    6    9   12   15
    

    所以我们可以使用模数%%和整数除法(地板)%/%分别确定行号和列号:

    (1:15-1) %% 3 + 1
    #  [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
    (1:15-1) %/% 3 + 1
    #  [1] 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5
    

    事实证明,最后一种方法要快得多(考虑到困难的部分是在 C 中完成的,这并不奇怪):

    microbenchmark::microbenchmark(
      a = which(B == min(B), arr.ind=TRUE),             # first answer, imperfect
      b = which(abs(B - min(B)) < 1e-9, arr.ind=TRUE),  # second, technically more correct
      c = {                                             # third, still correct, faster
        m <- which.min(B)
        c( (m-1) %% nrow(B) + 1, (m-1) %/% nrow(B) + 1 )
      }, times=10000)
    # Unit: microseconds
    #  expr min  lq     mean median   uq   max neval
    #     a 8.4 9.0 10.27770    9.5 10.4  93.5 10000
    #     b 9.0 9.6 10.94061   10.3 11.1 158.4 10000
    #     c 3.3 4.0  4.48250    4.2  4.7  38.7 10000
    

    【讨论】:

    • 太棒了!非常感谢!
    • CharlotteDeng,我想了一会儿,并补充了我认为非常重要的注释。我相信许多数据处理者不理解编程语言(包括但不限于 R)中浮点相等的细微差别,所以我确实建议您至少花 3 分钟时间阅读这些语言两个链接。一般来说,R 会尝试做“足够正确”的事情,但是当你最需要它时它会失败(或者忘记这个评论)。
    • 可以让which.min()处理数值相等的细微差别,并使用idx &lt;- which.min(B)然后恢复行和列索引c(row(B)[idx], col(B)[idx])
    • @MartinMorgan,直到我查看了源代码,我才确定,你是对的:因为它只对 &lt; (github.com/wch/r-source/blob/…) 进行测试,所以它是安全的浮点等式。
    猜你喜欢
    • 1970-01-01
    • 2020-10-11
    • 2015-05-21
    • 1970-01-01
    • 2014-06-17
    • 1970-01-01
    • 2012-12-02
    • 2021-11-10
    • 2020-11-29
    相关资源
    最近更新 更多