Sparkins
Sparkins

Reputation: 11

Identifying MULTIPLE minimum column names

I want to create a column that contains the name of the column(s) with the minimum values. So far, I have only come across code that gives you a single name. In the case of ties, you can choose a tie break method. However, what I want to do is to list all column names in the case of a tie.

Minimum code:

df <- data.frame(ColA = c(0, 4, 7, 7, 3),
             ColB = c(0, 2, 5, 3, 2),
             ColC = c(5, 10, 1, 3, 1),
             ColD = c(7, 3, 1, 3, 0))

To get a single column name I can do:

df$all.min.groups <- names(df)[apply(df, MARGIN = 1, FUN = which.min)]

Can you help me get all the column names that have the minimum value by row?

Upvotes: 1

Views: 129

Answers (2)

thelatemail
thelatemail

Reputation: 93938

Get the parallel minimum across each row, use this to generate the row/col locations of all minimums, and then grab the column names and split by row:

mins <- which(df == do.call(pmin, df), arr.ind=TRUE)
split(names(df)[mins[,"col"]], mins[,"row"])

#$`1`
#[1] "ColA" "ColB"
#
#$`2`
#[1] "ColB"
#
#$`3`
#[1] "ColC" "ColD"
#
#$`4`
#[1] "ColB" "ColC" "ColD"
#
#$`5`
#[1] "ColD"

Upvotes: 1

r2evans
r2evans

Reputation: 161085

If you want just a column of comma-separated strings, then perhaps

do.call(mapply, c(list(FUN = function(...) {
  dots <- unlist(list(...))
  toString(names(df[which(dots == min(dots))]))
}), df))
# [1] "ColA, ColB"       "ColB"             "ColC, ColD"       "ColB, ColC, ColD" "ColD"            

That would be good if this is "just informative". If, however, you intend to use them programmatically (perhaps to index on columns again later), then you may prefer to keep this as a list-column, in which case remove toString and use Map instead of mapply.

do.call(Map, c(list(f = function(...) 
  dots <- unlist(list(...))
  names(df[which(dots == min(dots))])
}), df))
# [[1]]
# [1] "ColA" "ColB"
# [[2]]
# [1] "ColB"
# [[3]]
# [1] "ColC" "ColD"
# [[4]]
# [1] "ColB" "ColC" "ColD"
# [[5]]
# [1] "ColD"

Note that this relies on numeric tests of quality, which should be fine as long as the numbers are not highly precise such that the technical limitations of digital storage of floating-point numbers become apparent, which seems unlikely given your sample data. However, you might want to reference Why are these numbers not equal?, Is floating point math broken?, and https://en.wikipedia.org/wiki/IEEE_754 anyway.

Upvotes: 1

Related Questions