Как найти местоположение (строка / столбец) минимального / максимального значения фрейма данных или матрицы (вопрос R) - PullRequest
0 голосов
/ 26 октября 2019

Я хочу найти расположение минимального или максимального значения фрейма данных или матрицы.

Например, позвольте мне использовать пример матрицы минимума (и давайте пока не будем рассматривать наличие тех же значений):

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)

Заранее спасибо!

1 Ответ

3 голосов
/ 26 октября 2019

Хотя which.min и друзья не поддерживают это напрямую, which(..., arr.ind=TRUE) делает:

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

Очень важно примечание: при этом есть две заметки:

  1. Это не сообщает о существовании связей;и

  2. Это предполагает, что будет работать равенство с плавающей запятой, что склонно к Почему эти числа не равны? и R FAQ 7.31 . Таким образом, хотя это, вероятно, работает большую часть времени, возможно , что это не всегда будет работать. В случае, если он не работает, он вернет 0-строку 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

Для фона: matrixв R это просто вектор, упорядоченный по столбцам.

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
...