Equivalent to rowMeans() for min()

前端 未结 6 1442
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-05 10:40

I have seen this question being asked multiple times on the R mailing list, but still could not find a satisfactory answer.

Suppose I a matrix m

相关标签:
6条回答
  • 2020-12-05 11:06

    Not particularly R-idiosyncratic, but surely the fastest method is just to use pmin and loop over columns:

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

    On my machine that takes just 3 times longer than rowMeans for the 1e+07x10 matrix, and is slightly faster than the do.call method via data.frame.

    0 讨论(0)
  • 2020-12-05 11:08
    library("sos")
    findFn("rowMin")
    

    gets a hit in the Biobase package, from 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 
    

    Not as fast as rowMeans, but a lot faster than apply(...,1,min)

    0 讨论(0)
  • 2020-12-05 11:10

    Quite late to the party, but as the author of matrixStats and in case someone spots this, please note that matrixStats::rowMins() is very fast these days, e.g.

    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
    
    0 讨论(0)
  • 2020-12-05 11:10

    I've been meaning to try out the new compiler package in R 2.13.0. This essentially follows the post outlined by 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)
    )
    

    And the results:

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

    Anticlimatic to say the least, though looks like you've gotten some other good options.

    0 讨论(0)
  • 2020-12-05 11:22

    If you want to stick to CRAN packages, then both the matrixStats and the fBasics packages have the function rowMins [note the s which is not in the Biobase function] and a variety of other row and column statistics.

    0 讨论(0)
  • 2020-12-05 11:27

    You could use pmin, but you would have to get each column of your matrix into a separate vector. One way to do that is to convert it to a data.frame then call pmin via do.call (since data.frames are lists).

    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 
    
    0 讨论(0)
提交回复
热议问题