Search code examples
rlistindices

How do I find the i j k indices of the maximum value in a list in r?


I have a list in R within which there is data (Data):

#create data
tmintest=array(1:100, c(12,256,512))

#create the list
Variable <- list(varName = c("tmin","tmin","tmin","tmin","tmin","tmin","tmin","tmin","tmin","tmin","tmin","tmin"),level = c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA))
Data     <- tmintest
xyCoords <- list(x = seq(-40.37,64.37,length.out=420), y = seq(25.37,72.37,length.out=189))
Dates <- list(start = seq(as.Date("2012-01-01"), as.Date("2015-12-31"), by="days"), end=seq(as.Date("2012-01-01"), as.Date("2015-12-31"), by="days"))
All <- list(Variable = Variable,Data=Data, xyCoords=xyCoords,Dates=Dates)

How can I find exactly where the maximum number in ALL$Data is occurring? For example, if it is the 4th row, 100th column on the first 'slice' or 'grid' I want back: [1,4,100].

I tried which.max(All$Data) but that just returns a single number?


Solution

  • which supports arr.ind, which returns the array indices of the condition. Unfortunately, there is no such argument for which.max, so we can compare the values against the max of the values.

    head( which(All$Data == max(All$Data), arr.ind = TRUE) )
    #      dim1 dim2 dim3
    # [1,]    4    9    1
    # [2,]    8   17    1
    # [3,]   12   25    1
    # [4,]    4   34    1
    # [5,]    8   42    1
    # [6,]   12   50    1
    

    I'll be a bit cautious here: strict equality tests of floating-point numbers can be a problem when the precision involves a good number of decimal places. See Why are these numbers not equal?, Is floating point math broken?, and https://en.wikipedia.org/wiki/IEEE_754 for a good discussion of this.

    The better test is one of strict inequality, looking for a tolerance. Here I'll use 1e-5 since we know that it is significantly smaller than the range of numbers (1 to 100), but if your real numbers have more precision, you may want something a little more suited for your needs.

    head( which( (max(All$Data) - All$Data) < 1e-5, arr.ind = TRUE) )
    #      dim1 dim2 dim3
    # [1,]    4    9    1
    # [2,]    8   17    1
    # [3,]   12   25    1
    # [4,]    4   34    1
    # [5,]    8   42    1
    # [6,]   12   50    1
    

    Note that if you drive that tolerance value 1e-5 too low, you may start to lose values. It won't happen here (because your data is much larger).