[R] Trying to avoid a loop -- which.max & max.col

Martin Maechler maechler at stat.math.ethz.ch
Wed Jan 24 09:01:20 CET 2001

>>>>> "TL" == Thomas Lumley <thomas at biostat.washington.edu> writes:

    TL> On Tue, 23 Jan 2001, Michael Roberts wrote:
    >>  Wow.  That was a quick reply. Thanks...  but see below.
    >> Michael J. Roberts Resource Economics Division, PMT USDA-ERS
    >> 202-694-5557
    >> >>> Thomas Lumley <thomas at biostat.washington.edu> 01/23 5:51 PM >>>
    >> On Tue, 23 Jan 2001, Michael Roberts wrote:
    >> > Hello:
    >> > 
    >> > Although I could write a loop to do the following, I would like
    >> to avoid this as it would be expensive.  Does anyone know if there
    >> is an R function that would make this faster?
    >> > 
    >> > Given a 3 dimensional array, say Z with dimensions {n,l,k}, I
    >> would like to create a matrix Y with dimensions {n,l}, each
    >> element of which contains the position {k} with the largest
    >> element that dimension.
    >> > 
    >> apply(z,c(1,2),max)
    >> This is close, but not exactly what I am looking for.  I don't want
    >> the maximum value, but the position of the maximum value.  Is there
    >> something like an "argmax" I could put in for max?

    TL> apply(z,1:2, function(x) which(x==max(x)))

and exactly because the above is not quite efficient,
I had added the 
		which.max   (and which.min)
		~~~~~~~~~        ~~~~~~~~~
functions to R (1.1.0).
	apply(z,1:2, which.max)

Note further that we have the (original MASS) function


to work for matrices which again is more efficient than 
      apply(mat, 1, which.max)
{and not quite equivalent: 
 max.col breaks ties at random, which.max always gives the first max}.

Now, you can reshape your rank-3 array {n,l,k} into a matrix {n*l, k}
use  max.col() on that matrix and reshape the {n * l} vector to the desired
{n, l} matrix:

x <- rnorm(50000)

ar <- array(x, dim = c(25,40,50))
system.time(m1 <- apply(ar, 1:2, which.max))

  mat <- ar
  dim(mat) <- c(25*40, 50)
  m2 <- matrix(max.col(mat), 25, 40)

all(m1 == m2) # these two are identical

## On my Linux machine, the 
## max.col() version uses 0.03 sec  compared to 0.10 for the apply() solution
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch

More information about the R-help mailing list