Самый быстрый способ сортировки и сортировки строк матрицы [r] - PullRequest
0 голосов
/ 06 марта 2020

У меня есть матрица, заполненная несколько случайными элементами. Мне нужно, чтобы каждая строка сортировалась в порядке убывания, затем вызывается функция для матрицы, и, наконец, результирующая матрица должна быть отсортирована в исходном порядке.

Это быстро выполняется по вектору, как показано здесь , но какой самый быстрый способ сделать это для каждой строки в матрице? Прямо сейчас я делаю:

# Example matrix
m <- matrix(runif(100), nrow = 25, ncol = 4)

# Get the initial order by row
om <- t(apply(m, 1, order, decreasing = T))

sm <- m
for (i in seq_len(nrow(m))) {
  sm[i, ] <- sm[i, om[i, ]]
}

# ** Operations performed on sm **

# Then unsort
for (i in seq_len(nrow(m))) {
  sm[i, ] <- sm[i, order(om[i, ])]
}

# sm is now sorted by-row in the same order as m

Есть ли какой-либо способ, заданный om в приведенном выше, для сортировки и сортировки, избегая при этом для l oop или функции apply (обе из которых выполняют эту операцию очень медленно для большого м). Спасибо!

Редактировать: Здесь есть указатели: Самый быстрый способ сортировки каждой строки большой матрицы в R Операция выполняется внутри функции, которая уже вызывается с использованием параллельного интерфейса, поэтому эта операция должно быть сделано с использованием серийного кода.

1 Ответ

3 голосов
/ 06 марта 2020

Строковая сортировка кажется простой. Чтобы вернуть исходный заказ (не отсортировать), нам нужен построчный ранг , а не их порядок. После этого, то, что работает для сортировки столбцов в @ Jo sh O'Brien's answer , мы можем адаптировать для строк.

Решение Base R:

rr <- t(apply(m, 1, rank))  ## get initial RANKS by row
sm <- t(apply(m, 1, sort))  ## sort m

##  DOING STUFF HERE  ##

sm[] <- sm[cbind(as.vector(row(rr)), as.vector(rr))]  ## un-sort
all(m == sm)  ## check
# [1] TRUE

Кажется, работает.

В вашем связанном ответе функция rowSort пакета Rfast хорошо выделяется с точки зрения производительности, которая может охватывать проблему сортировки. Кроме того, есть также функция rowRanks, которая будет охватывать нашу проблему ранжирования. Так что мы можем избежать apply.

Давайте попробуем.

m[1:3, ]
#           [,1]      [,2]      [,3]        [,4]
# [1,] 0.9148060 0.5142118 0.3334272 0.719355838
# [2,] 0.9370754 0.3902035 0.3467482 0.007884739
# [3,] 0.2861395 0.9057381 0.3984854 0.375489965

library(Rfast)
rr <- rowRanks(m)  ## get initial RANKS by row
sm <- rowSort(m)   ## sort m
sm[1:3, ]  # check
#            [,1]      [,2]      [,3]      [,4]
# [1,] 0.36106962 0.4112159 0.6262453 0.6311956
# [2,] 0.01405302 0.2171577 0.5459867 0.6836634
# [3,] 0.07196981 0.2165673 0.5739766 0.6737271

##  DOING STUFF HERE  ##

sm[] <- sm[cbind(as.vector(row(rr)), as.vector(rr))]  ## un-sort
all(sm == m)  ## check
# [1] TRUE

Dito.

Тест

m.test <- matrix(runif(4e6), ncol = 4)
dim(m.test)
# [1] 1000000       4

# Unit: milliseconds
#     expr        min       lq       mean     median         uq        max neval cld
#    Rfast   897.6286   910.91   956.6259   924.1914   986.1246   1048.058     3 a  
#    baseR 87931.2824 88004.73 95659.8671 88078.1737 99524.1594 110970.145     3   c
#  forloop 58927.7784 59434.54 60317.3903 59941.2930 61012.1963  62083.100     3  b 

Не так уж плохо! !


Данные / Код:

set.seed(42)

m <- matrix(runif(100), nrow = 25, ncol = 4)

## benchmark
m.test <- matrix(runif(4e6), ncol = 4)

microbenchmark::microbenchmark(
  Rfast={
    rr <- rowRanks(m.test)
    sm <- rowSort(m.test)
    sm[] <- sm[cbind(as.vector(row(rr)), as.vector(rr))]},
  baseR={
    rr <- t(apply(m.test, 1, rank))
    sm <- t(apply(m.test, 1, sort))
    sm[] <- sm[cbind(as.vector(row(rr)), as.vector(rr))]
  },
  forloop={
    om <- t(apply(m.test, 1, order, decreasing = T))
    sm <- m.test
    for (i in seq_len(nrow(m.test))) {
      sm[i, ] <- sm[i, om[i, ]]
    }
    for (i in seq_len(nrow(m.test))) {
      sm[i, ] <- sm[i, order(om[i, ])]
    }
  }, times=3L
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...