虽然which.min 和朋友不直接支持这一点,但which(..., arr.ind=TRUE) 支持:
which(B == min(B), arr.ind=TRUE)
# row col
# [1,] 1 4
非常重要旁注:这样做有两个注意事项:
这不报告存在关系;和
-
这假设浮点相等会起作用,这很容易出现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