vignettes/intro.Rmd
intro.Rmd
Elo is a system of ratings/rankings (named after its creator, Arpad Elo) for pairwise matchups. In short, pairs of “teams” (“A” and “B”) begin a match with rankings \(R_A\) and \(R_B\). The result (“score”) of the game is coded as 0/0.5/1 for loss/tie/win, respectively. The prior expectation of this result can be expressed as \[P_A = \frac{1}{1 + 10^{(R_B - R_A) / 400}}\] \[P_B = \frac{1}{1 + 10^{(R_A - R_B) / 400}} = 1 - P_A\] where \[P_i\] is the prior probability that team \(i\) wins the match.
After each match, ratings are updated as follows: \[R^{new}_A = R_A + K(S_A - P_A)\] \[R^{new}_B = R_B + K(S_B - P_B) = R_B + K(1 - S_A - (1 - P_A)) = R_B - K(S_A - P_A)\] where \(S_i\) is the score of team \(i\) (0/0.5/1) and \(K\) is an update weight (commonly called the “k-factor”).
Therefore, we see that the system as a whole (all teams) retains (“conserves”) its total sum of Elo ratings; for every rating point team A gains/loses, team B loses/gains the same amount.
elo
PackageThe elo
package includes functions to address all kinds of Elo calculations.
Most functions begin with the prefix “elo.”, for easy autocompletion.
Vectors or scalars of Elo scores are denoted elo.A
or elo.B
.
Vectors or scalars of wins by team A are denoted by wins.A
.
Vectors or scalars of win probabilities are denoted by p.A
.
Vectors of team names are denoted team.A
or team.B
.
To calculate the probability team.A beats team.B, use elo.prob()
:
## [1] 0.500000 0.359935
To calculate the score update after the two teams play, use elo.update()
:
wins.A <- c(1, 0)
elo.update(wins.A, elo.A, elo.B, k = 20)
## [1] 10.0000 -7.1987
To calculate the new Elo scores after the update, use elo.calc()
:
elo.calc(wins.A, elo.A, elo.B, k = 20)
## elo.A elo.B
## 1 1510.000 1490.000
## 2 1492.801 1607.199
It may be helpful to calculate wins.A
from raw scores:
## elo.A elo.B
## 1 1510.000 1490.000
## 2 1492.801 1607.199
All of the “basic” functions accept formulas as input:
dat <- data.frame(elo.A = c(1500, 1500), elo.B = c(1500, 1600),
wins.A = c(1, 0), k = 20)
form <- wins.A ~ elo.A + elo.B + k(k)
elo.prob(form, data = dat)
## [1] 0.500000 0.359935
elo.update(form, data = dat)
## [1] 10.0000 -7.1987
elo.calc(form, data = dat)
## elo.A elo.B
## 1 1510.000 1490.000
## 2 1492.801 1607.199
Note that for elo.prob()
, formula =
can be more succinct:
elo.prob(~ elo.A + elo.B, data = dat)
## [1] 0.500000 0.359935
We can even adjust the Elos, for, e.g., home-field advantage.
## elo.A elo.B
## 1 1509.712 1490.288
## 2 1492.534 1607.466