首页 > 解决方案 > 如何找到数据框或矩阵的最小值/最大值的位置(行/列)(R问题)

问题描述

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

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

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

我想要的输出是:

行数 = 1

column.number = 4

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

提前致谢!

标签: rmatrixdata-manipulation

解决方案


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

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

非常重要的附注:执行此操作时有两个注意事项:

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

  2. 这假设浮点相等会起作用,这很容易出现为什么这些数字不相等?R 常见问题解答 7.31。因此,虽然这可能在大多数情况下都有效,但它并不总是有效是可行的。如果它不起作用,它将返回一个 0-row matrix。一个缓解步骤是引入容差,例如

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

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

更快的选择

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

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

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

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

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

(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

推荐阅读