Skip to contents

Rank elements based on their scores.

Usage

doRanking(scores, compare = NULL, decreasing = TRUE)

Arguments

scores

A vector or list representing each element's score. If names(scores) is not NULL, those will be used as element names. Else a number sequence corresponding to the elements is generated.

compare

Optional comparison function taking in two elements and returning a numerical value based on the relation between these two elements. If set to NULL, the default order() function is called. See details for more information.

decreasing

If TRUE (default), elements with higher scores are ranked higher.

Value

A list of type SocialRanking. Each element of the list contains a vector of elements in powerRelation$elements that are indifferent to one another.

Details

All ranking solutions in the package are tied to the scores or score vectors of the elements. For these kinds of solutions, doRanking() offers a simple way that turns a (named) vector or list of scores for each element into a SocialRanking object. For example, doRanking(c(a=1,b=2)) produces b > a (\(b P^\succsim a\)), because b with a score of 2 should be placed higher than a with a score of 1.

Ranking solutions in the package include lexcelRanking(), ordinalBanzhafRanking() and L1Ranking(), among others. These functions take a power relation, calculate the scores of each element and returns a SocialRanking object.

R natively supports sorting for vectors, but not for lists. If the use of lists is necessary, or if the native sort method in vectors does not produce the desired results, there are two possible ways to solve this:

  1. by the introduction of custom S3 classes, or

  2. by setting the compare parameter in doRanking().

For S3 classes, the class for the score object has to be set and the == and > (and [ for lists) operators overloaded. I.e., lexcelScores() returns a list with the custom class LexcelScores that implements ==.LexcelScores, >.LexcelScores, [.LexcelScores and is.na.LexcelScores.

In cases where we only want to experiment, introducing new S3 classes can be cumbersome. As an alternative, the compare parameter can be assigned a function. This function must take two parameters, i.e., function(a, b), where a and b are the scores of two arbitrary elements. The function then must return one of the following:

  • > 0 (positive value) if score a is ranked higher than score b,

  • < 0 (negative value) if score a is ranked lower than score b, or

  • = 0 if both scores a and b are considered equal.

In doRanking(c(a=3,b=2,c=2), compare = function(a,b) a - b), the compare function returns a positive value of the first parameter is larger than the second. a has the highest value and will there for be ranked highest, a > b ~ c.

Conversely, doRanking(c(a=3,b=2,c=2), compare = function(a,b) b - a) favors elements with lower scores, resulting in the element ranking b ~ c > a.

See also

Examples

doRanking(c(a=1,b=2))
#> b > a
# b > a

doRanking(c(a=2,b=2))
#> a ~ b
# a ~ b

# a custom ranking function. Here, we implement the following ranking solution:
# disregard any big coalitions and only rank elements based on their individual performances
# iRj if and only if {i} >= {j}
singletonRanking <- function(pr) {
  scores <- sapply(pr$elements, equivalenceClassIndex, powerRelation = pr)
  # note that coalitions in higher indexed equivalence classes are less preferable
  # hence, scores should be sorted in an increasing order
  doRanking(scores, decreasing = FALSE)
}

pr <- as.PowerRelation("abc > ab > ac > b ~ c ~ bc > a")
singletonRanking(pr)
#> b ~ c > a
# b ~ c > a

# a reverse lexcel ranking, where vectors are compared right to left
# here, we introduce a compare function. It returns:
# * 0, if a and b are identical
# * a positive value, if a[i] > b[i] and every value after that is equal
# * a negative value, if a[i] < b[i] and every value after that is equal
reverseLexcelCompare <- function(a, b) {
  i <- which(a != b) |> rev()
  if(length(i) == 0) 0
  else a[i[1]] - b[i[1]]
}

scores <- unclass(cumulativeScores(pr))

# R cannot natively sort a class. Instead:
# Method 1 - utilize the compare parameter
doRanking(scores, compare = reverseLexcelCompare)
#> b > c > a


# Method 2 - introduce S3 class
`[.RevLex` <- function(x, i, ...) structure(unclass(x)[i], class = "RevLex")
`==.RevLex` <- function(a, b) reverseLexcelCompare(a[[1]],b[[1]]) == 0
`>.RevLex` <- function(a, b) reverseLexcelCompare(a[[1]],b[[1]]) > 0
is.na.RevLex <- function(x) FALSE
doRanking(structure(scores, class = "RevLex"))
#> Error in rank(x, ties.method = "min", na.last = "keep"): unimplemented type 'list' in 'greater'

stopifnot(
  doRanking(scores, compare = reverseLexcelCompare) ==
  doRanking(structure(scores, class = "RevLex"))
)
#> Error in rank(x, ties.method = "min", na.last = "keep"): unimplemented type 'list' in 'greater'