Sebastian
Sebastian

Reputation: 633

Get the row and column name of the minimum element of a matrix

I need to get the row and column name of the smallest element of a matrix

> mat = matrix(data=runif(12), nrow = 4, ncol=4)
> rownames(mat) = colnames(mat) = letters[1:4]
> 
> mat
  a         b         c         d
a 0.3167865 0.6958895 0.4233572 0.3167865
b 0.1042599 0.1552235 0.8461520 0.1552235
c 0.6286461 0.9749868 0.2390978 0.6286461
d 0.5923721 0.7823673 0.8427426 0.5923721
> min = min(mat)
> min
> 0.1042599

In this example I'd like to get "a" and "b"

Upvotes: 52

Views: 34199

Answers (2)

nisetama
nisetama

Reputation: 8863

When there are multiple minimum values, the first two options below only return the row and column index of the first minimum value but the last two options return the row and column index of all minimum values:

set.seed(0)
m=matrix(round(runif(1e6,0,1e5)),1e3)

b=microbenchmark(times=100,
  arrayInd(which.min(m),dim(m)),
  {w=which.min(m);c((w-1)%%nrow(m),(w-1)%/%nrow(m))+1},
  which(m==min(m),arr.ind=T),
  {w=which(m==min(m));cbind((w-1)%%nrow(m),(w-1)%/%nrow(m))+1}
)

a=aggregate(b$time,list(gsub(" ","",gsub("     ",";",gsub("\\{    ","{",b$expr)))),median)
a=a[order(a[,2]),]
writeLines(paste(sprintf("%.3f",a[,2]/min(a[,2])),gsub(" ","",a[,1])))

Result:

1.000 arrayInd(which.min(m),dim(m))
1.002 {w=which.min(m);c((w-1)%%nrow(m),(w-1)%/%nrow(m))+1}
3.183 {w=which(m==min(m));cbind((w-1)%%nrow(m),(w-1)w%/%nrow(m))+1}
3.183 which(m==min(m),arr.ind=T)

Upvotes: 1

bnaul
bnaul

Reputation: 17636

> inds = which(mat == min(mat), arr.ind=TRUE)
> inds
  row col
a   1   2
> rnames = rownames(mat)[inds[,1]]
> cnames = colnames(mat)[inds[,2]]

This will give you the row/column names for each entry that equals the minimum value; if you just want the first one, you could only check inds[1,1] and inds[1,2].

Upvotes: 58

Related Questions