Consider the following matrix m
:
ca bsa rd zaa
ada 3 4 3 2
aca 1 4 5 2
ara 3 4 3 2
ava 3 4 5 2
I'm trying to find, for each row, the minimum value and return a data.frame in the form of:
q s d
1 ada zaa 2
2 aca ca 1
3 ara zaa 2
4 ava zaa 2
Right now I'm doing:
res <- t(sapply(seq(nrow(m)), function(i) {
j <- which.min(m[i,])
c(q = rownames(m)[i],
s = colnames(m)[j],
d = m[i,j])}))
res <- data.frame(res)
res$d <- as.numeric(res$d)
I'm looking for a better way to build this.
It feels rather inefficient to build res
using c()
(coercing all the components to the same type) then convert it to a data.frame and finally change d
to numeric in order to obtain the following structure:
'data.frame': 4 obs. of 3 variables:
$ q: Factor w/ 4 levels "aca","ada","ara",..: 2 1 3 4
$ s: Factor w/ 2 levels "ca","zaa": 2 1 2 2
$ d: num 2 1 2 2
I would also need to handle a case where there could be multiple minima
Data
m <- structure(c(3, 1, 3, 3, 4, 4, 4, 4, 3, 5, 3, 5, 2, 2, 2, 2), .Dim = c(4L,
4L), .Dimnames = list(c("ada", "aca", "ara", "ava"), c("ca", "bsa", "rd", "zaa")))
You may find the column index of the minimum value for each row by using max.col
on the negated version of the matrix.
col_id <- max.col(-m)
data.frame(q = rownames(m), s = colnames(m)[col_id],
d = m[cbind(1:length(col_id), col_id)])
# q s d
# 1 ada zaa 2
# 2 aca ca 1
# 3 ara zaa 2
# 4 ava zaa 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With