2
$\begingroup$

The code below is generating the mode value considering the columns Method1, Method2, Method3 and Method4. However, notice that for alternative 10 and 12 it has the same mode value, that is, it has a value of 2. However, I would like my Mode column to have different values, as if it were a rank. Therefore, the alternative that had Mode=1 is the best, but I have no way of knowing the second best alternative, because it has two numbers 2 in the Mode column. Do you have suggestions on what approach I can take?

database<-structure(list(Alternatives = c(3, 4, 5, 6, 7, 8, 9, 10, 11, 12), 
    Method1 = c(1L, 10L, 7L, 8L, 9L, 6L, 5L, 3L, 4L, 2L), Method2 = c(1L, 
    8L, 6L, 7L, 10L, 9L, 4L, 2L, 3L, 5L), Method3 = c(1L, 
    10L, 7L, 8L, 9L, 6L, 4L, 2L, 3L, 5L), Method4 = c(1L, 
    9L, 6L, 7L, 10L, 8L, 5L, 3L, 4L, 2L)), class = "data.frame", row.names = c(NA, 
10L))

 ModeFunc <- function(Vec) {
    tmp <- sort(table(Vec),decreasing = TRUE)
    Nms <- names(tmp)
    if(max(tmp) > 1) {
      as.numeric(Nms[1])
    } else NA}
  
  
  output <- database |> rowwise() |> 
    mutate(Mode = ModeFunc(c_across(Method1:Method4))) %>% 
    data.frame()

> output
   Alternatives Method1 Method2 Method3 Method4 Mode
1             3       1       1       1       1    1
2             4      10       8      10       9   10
3             5       7       6       7       6    6
4             6       8       7       8       7    7
5             7       9      10       9      10    9
6             8       6       9       6       8    6
7             9       5       4       4       5    4
8            10       3       2       2       3    2
9            11       4       3       3       4    3
10           12       2       5       5       2    2

@prubin answer

output |> mutate(Weight = Mode +
1/ nrow(database) * ((Method1 + Method2 + Method3 + Method4) / 4)) |>
 mutate(rank = rank(Weight))

     Alternatives Method1 Method2 Method3 Method4 Mode Weight rank
1             3       1       1       1       1    1  1.100    1
2             4      10       8      10       9   10 10.925   10
3             5       7       6       7       6    6  6.650    6
4             6       8       7       8       7    7  7.750    8
5             7       9      10       9      10    9  9.950    9
6             8       6       9       6       8    6  6.725    7
7             9       5       4       4       5    4  4.450    5
8            10       3       2       2       3    2  2.250    2
9            11       4       3       3       4    3  3.350    4
10           12       2       5       5       2    2  2.350    3
$\endgroup$
2
  • $\begingroup$ When there are ties for the mode in a given row, you want to select one of them so that the resulting Mode column takes distinct values? $\endgroup$
    – RobPratt
    Jul 2, 2022 at 14:00
  • $\begingroup$ Exactly @RobPratt! $\endgroup$
    – Antonio
    Jul 2, 2022 at 14:22

2 Answers 2

3
$\begingroup$

There is no guarantee you can avoid ties using mode (or anything else, if it is possible for two alternatives to have identical scores and thus be indistinguishable). Rob's approach (which I endorse) works in your example, but with somewhat different data the integer program could wind up being infeasible.

A simple way to break most (but possibly not all ties) would be to create a weight column that is equal to the mode plus a constant (maybe 0.1 or 0.01, depending on the scale of the data) times the mean for that alternative. So alternative 10 would get weight 2.25 (using 0.1 for the multiplier) while alternative 12 would get weight 2.35. That still does not exclude the possibility of ties, but it would hopefully reduce the frequency of them.

$\endgroup$
4
  • $\begingroup$ Thanks both for the replies. @prubin, in your way, I think I can solve it more easily. Just to understand, the formula would be: Weight =(Mode+Constant).alternative mean. In the case of alternative 10, the Mode is 2 and the constant 0.1. And alternative mean, how did you calculate to get the weight of 2.25? $\endgroup$
    – Antonio
    Jul 2, 2022 at 20:04
  • 1
    $\begingroup$ Weight = Mode + (constant * mean). So for alternative 10, the mode is 2, the mean is (3 + 2 + 2 + 3)/4 = 2.5, and the weight is 2 + c * 2.5 where c is the constant. With c = 0.1, that gets you a weight of 2.25. You need c small enough that c * mean < 1 for the largest mean of any alternative. $\endgroup$
    – prubin
    Jul 2, 2022 at 21:20
  • $\begingroup$ Thanks for the explanation @prubin. I inserted your answer in the question. I made the rank considering the lower the weight, the better the alternative. As I had commented on the question Mode=1 is the best option, that's why I left lower weight, better option, right? Second, I was left with a doubt: if it doesn't have a mode value. If it were different values for all methods, mode would be NA. And if it considered 0 instead of NA, the weight would be too small because it wouldn't have the mode value to add to. Any suggestion to resolve this? $\endgroup$
    – Antonio
    Jul 3, 2022 at 0:31
  • $\begingroup$ Yes, if lowest mode is best, then lowest weight is best. As far as all methods producing different scores, I would say that every value is a mode. So just as 3 and 4 are both modes for your alternative 11, an alternative with scores (2, 3, 4, 5) would have modes 2, 3, 4 and 5. So your mode function could pick any of those values, add 0.35 (.1 times the mean), and turn that into a rank. Bottom line: you might want to rethink whether mode is the best way to rank your data. $\endgroup$
    – prubin
    Jul 3, 2022 at 3:03
4
$\begingroup$

You are looking for a transversal or system of distinct representatives. One approach is to construct a bipartite graph with a left node for each alternative $i$, a right node for each mode $j$, and an edge $(i,j)$ if alternative $i$ has $j$ as a possible mode. Now find a perfect matching in this graph. You can do so via integer linear programming by introducing binary decision variable $x_{ij}$ to indicate whether edge $(i,j)$ is selected and imposing linear constraints: \begin{align} \sum_j x_{ij} &= 1 &&\text{for all $i$} \\ \sum_i x_{ij} &= 1 &&\text{for all $j$} \end{align}

Your example above has $10+10=20$ nodes and $17$ edges, and it turns out that there are two solutions.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.