相当于min()的rowMeans()

时间:2011-06-14 02:38:11

标签: r optimization

我在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倍,有没有办法加快速度?

6 个答案:

答案 0 :(得分:17)

您可以使用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 

答案 1 :(得分:14)

派对相当晚,但作为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

答案 2 :(得分:8)

如果您想坚持CRAN软件包,那么matrixStatsfBasics软件包都有rowMins函数[注意s不是Biobase在{{1}}函数]和各种其他行和列统计信息。

答案 3 :(得分:5)

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

来自Bioconductor的Biobase包......

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)

快很多

答案 4 :(得分:5)

我一直想在R 2.13.0中试用新的compiler包。这基本上遵循Dirk here概述的帖子。

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

至少可以说是反思,虽然看起来你已经有了一些其他好的选择。

答案 5 :(得分:2)

不是特别R-idiosyncratic,但肯定最快的方法是使用pmin并循环列:

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

在我的机器上,对于1e + 07x10矩阵,其行程仅比rowMeans长3倍,并且通过do.calldata.frame方法略快。