Подтвердить что ты не робот

Эквивалентно rowMeans() для min()

Я часто задавал этот вопрос несколько раз в списке рассылки R, но не смог найти удовлетворительного ответа.

Предположим, что я матрица m

m <- matrix(rnorm(10000000), ncol=10) 

Я могу получить среднее значение для каждой строки:

system.time(rowMeans(m))  
   user  system elapsed   
  0.100   0.000   0.097

Но получение минимального значения каждой строки на

system.time(apply(m,1,min))  
   user  system elapsed   
 16.157   0.400  17.029

занимает более 100 раз, есть ли способ ускорить это?

4b9b3361

Ответ 1

Вы можете использовать pmin, но вам нужно будет получить каждый столбец вашей матрицы в отдельный вектор. Один из способов сделать это - преобразовать его в data.frame, затем вызвать pmin через do.call (так как data.frames - это списки).

system.time(do.call(pmin, as.data.frame(m)))
#    user  system elapsed 
#   0.940   0.000   0.949 
system.time(apply(m,1,min))
#    user  system elapsed 
#   16.84    0.00   16.95 

Ответ 2

Довольно поздно вечеринке, но как автор matrixStats, и в случае, если кто-то заметил это, обратите внимание, что matrixStats::rowMins() очень быстро в эти дни, например,

library(microbenchmark)
library(Biobase)     # rowMin()
library(matrixStats) # rowMins()
options(digits=3)

m <- matrix(rnorm(10000000), ncol=10) 

stats <- microbenchmark(
  rowMeans(m), ## A benchmark by OP
  rowMins(m),
  rowMin(m),
  do.call(pmin, as.data.frame(m)),
  apply(m, MARGIN=1L, FUN=min),
  times=10
)

> stats
Unit: milliseconds
                             expr    min     lq   mean median     uq    max
                      rowMeans(m)   77.7   82.7   85.7   84.4   90.3   98.2
                       rowMins(m)   72.9   74.1   88.0   79.0   90.2  147.4
                        rowMin(m)  341.1  347.1  395.9  383.4  395.1  607.7
  do.call(pmin, as.data.frame(m))  326.4  357.0  435.4  401.0  437.6  657.9
 apply(m, MARGIN = 1L, FUN = min) 3761.9 3963.8 4120.6 4109.8 4198.7 4567.4

Ответ 3

Если вы хотите придерживаться пакетов CRAN, то пакеты matrixStats и fBasics имеют функцию rowMins [обратите внимание на s, которая не находится в функции Biobase], и множество другие статистики строк и столбцов.

Ответ 4

library("sos")
findFn("rowMin")

получает удар в пакете Biobase, от Bioconductor...

source("http://bioconductor.org/biocLite.R")
biocLite("Biobase")

m <- matrix(rnorm(10000000), ncol=10)
system.time(rowMeans(m))
##   user  system elapsed 
##  0.132   0.148   0.279 
system.time(apply(m,1,min))
##   user  system elapsed 
## 11.825   1.688  13.603
library(Biobase)
system.time(rowMin(m))
##    user  system elapsed 
##  0.688   0.172   0.864 

Не так быстро, как rowMeans, но намного быстрее, чем apply(...,1,min)

Ответ 5

Я хотел попробовать новый пакет compiler в R 2.13.0. Это в основном следует за сообщением, описанным Dirk здесь.

library(compiler)
library(rbenchmark)
rowMin <- function(x, ind) apply(x, ind, min)
crowMin <- cmpfun(rowMin)

benchmark(
      rowMin(m,1)
    , crowMin(m,1)
    , columns=c("test", "replications","elapsed","relative")
    , order="relative"
    , replications=10)
)

И результаты:

           test replications elapsed relative
2 crowMin(m, 1)           10 120.091   1.0000
1  rowMin(m, 1)           10 122.745   1.0221

Актиматический, если не сказать больше, хотя, похоже, у вас есть другие хорошие варианты.

Ответ 6

Не особенно R-идиосинкразированный, но, безусловно, самым быстрым методом является просто использовать pmin и перебирать столбцы:

x <- m[,1]
for (i in 2:ncol(m)) x <- pmin(x, m[,i])

На моей машине, которая занимает всего 3 раза дольше, чем rowMeans для матрицы 1e + 07x10, и немного быстрее, чем метод do.call через data.frame.