Reputation: 633
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
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
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