rate_keener(cr_data, ..., fill = 0, force_nonneg_h2h = TRUE,
skew_fun = skew_keener, normalize_fun = normalize_keener, eps = 0.001)
rank_keener(cr_data, ..., fill = 0, force_nonneg_h2h = TRUE,
skew_fun = skew_keener, normalize_fun = normalize_keener, eps = 0.001,
keep_rating = FALSE, ties = c("average", "first", "last", "random", "max",
"min"), round_digits = 7)
skew_keener(x)
normalize_keener(mat, cr_data)
cr_data | Competition results in format ready for as_longcr(). |
---|---|
... | Head-to-Head expression (see h2h_mat()). |
fill | A single value to use instead of NA for missing pairs. |
force_nonneg_h2h | Whether to force nonnegative values in Head-to-Head matrix. |
skew_fun | Skew function. |
normalize_fun | Normalization function. |
eps | Coefficient for forcing irreducibility. |
keep_rating | Whether to keep rating column in ranking output. |
ties | Value for |
round_digits | Value for |
x | Argument for |
mat | Argument for |
rate_keener()
returns a tibble with columns
player
(player identifier) and rating_keener
(Keener
rating). Sum of all ratings should be equal to 1. Bigger
value indicates better player performance.
rank_keener()
returns a tibble
with columns player
, rating_keener
(if
keep_rating = TRUE
) and ranking_keener
(Keener ranking
computed with round_rank()
).
skew_keener()
returns skewed vector of the same length as x
.
normalize_keener()
returns normalized matrix with the same dimensions as
mat
.
Keener rating method is based on Head-to-Head matrix of the competition results. Therefore it can be used for competitions with variable number of players. Its algorithm is as follows:
Compute Head-to-Head matrix of competition results based on Head-to-Head
expression supplied in ...
(see h2h_mat() for
technical details and section Design of Head-to-Head values for design
details). Head-to-Head values are computed based only on the games between
players of interest (see Players). Ensure that there are no NA
s by using
fill
argument. If force_nonneg_h2h
is TRUE
then the minimum value is
subtracted (in case some Head-to-Head value is strictly negative).
Update raw Head-to-Head values (denoted as S) with the pair-normalization: a_ij = (S_ij + 1) / (S_ij + S_ji + 2). This step should make comparing different players more reasonable.
Skew Head-to-Head values with applying skew_fun
to them. skew_fun
should take numeric vector as only argument. It should return skewed vector.
The default skew function is skew_keener()
. This step should make abnormal
results not very abnormal. To omit this step supply skew_fun = NULL
.
Normalize Head-to-Head values with normalize_fun
using cr_data
.
normalize_fun
should take Head-to-Head matrix as the first argument and
cr_data
as second. It should return normalized matrix. The default
normalization is normalize_keener()
which divides Head-to-Head value of
'player1'-'player2' matchup divided by the number of games played by
'player1' (error is thrown if there are no games). This step should take into
account possibly not equal number of games played by players. To omit this
step supply normalize_keener = NULL
.
Add small value to Head-to-Head matrix to ensure its irreducibility. If
all values are strictly positive then this step is omitted. In other case
small value is computed as the smallest non-zero Head-to-Head value
multiplied by eps
. This step is done to ensure applicability of
Perron-Frobenius theorem.
Compute Perron-Frobenius vector of the resultant matrix, i.e. the strictly positive real eigenvector (which values sum to 1) for eigenvalue (which is real) of the maximum absolute value. This vector is Keener rating vector.
If using normalize_keener()
in normalization step, ensure to analyze
players which actually played games (as division by a number of played games
is made). If some player didn't play any game, en error is thrown.
Head-to-Head values in these functions are assumed to follow the property which can be equivalently described in two ways:
In terms of matrix format: the more Head-to-Head value in row i and column j the better player from row i performed than player from column j.
In terms of long format: the more Head-to-Head value the better player1 performed than player2.
This design is chosen because in most competitions the goal is to score
more points and not less. Also it allows for more smooth use of
h2h_funs from comperes
package.
comperank
offers a possibility to handle certain set of players. It is done
by having player
column (in longcr format) as factor
with levels specifying all players of interest. In case of factor the result
is returned only for players from its levels. Otherwise - for all present
players.
James P. Keener (1993) The Perron-Frobenius theorem and the ranking of football teams. SIAM Review, 35(1):80–93, 1993.
#> # A tibble: 5 x 2
#> player rating_keener
#> <chr> <dbl>
#> 1 Duke 0.0671
#> 2 Miami 0.351
#> 3 UNC 0.158
#> 4 UVA 0.161
#> 5 VT 0.263 #> # A tibble: 5 x 2
#> player ranking_keener
#> <chr> <dbl>
#> 1 Duke 5
#> 2 Miami 1
#> 3 UNC 4
#> 4 UVA 3
#> 5 VT 2#> # A tibble: 5 x 3
#> player rating_keener ranking_keener
#> <chr> <dbl> <dbl>
#> 1 Duke 0.0671 5
#> 2 Miami 0.351 1
#> 3 UNC 0.158 4
#> 4 UVA 0.161 3
#> 5 VT 0.263 2#> # A tibble: 5 x 2
#> player rating_keener
#> <chr> <dbl>
#> 1 Duke 0.0898
#> 2 Miami 0.295
#> 3 UNC 0.165
#> 4 UVA 0.189
#> 5 VT 0.261 #> # A tibble: 5 x 2
#> player rating_keener
#> <chr> <dbl>
#> 1 Duke 0.162
#> 2 Miami 0.335
#> 3 UNC 0.136
#> 4 UVA 0.149
#> 5 VT 0.219#> # A tibble: 5 x 2
#> player rating_keener
#> <chr> <dbl>
#> 1 Duke 0.128
#> 2 Miami 0.300
#> 3 UNC 0.153
#> 4 UVA 0.161
#> 5 VT 0.257