Here I analyse a series of Grand Prix motorcycling race results using
the hyper2 package which implements the Plackett-Luce likelihood
function. Consider the following dataset, taken from Wikipedia:
moto_table <- read.table("motoGP_2019.txt")
head(moto_table)
## QAT ARG AME SPA FRA ITA CAT NED GER CZE AUT GBR RSM ARA THA JPN AUS MAL VAL points
## Marquez 2 1 Ret 1 1 2 1 2 1 1 2 2 1 1 1 1 1 2 1 420
## Dovizioso 1 3 4 4 2 3 Ret 4 5 2 1 Ret 6 2 4 3 7 3 4 269
## Vinales 7 Ret 11 3 Ret 6 Ret 1 2 10 5 3 3 4 3 4 Ret 1 6 211
## Rins 4 5 1 2 10 4 4 Ret Ret 4 6 1 Ret 9 5 7 9 5 5 205
## Quartararo 16 8 7 Ret 8 10 2 3 Ret 7 3 Ret 2 5 2 2 Ret 7 2 192
## Petrucci 6 6 6 5 3 1 3 6 4 8 9 7 10 12 9 9 Ret 9 Ret 176
Each row is a driver (rider?) and each column (after the first) a
venue. Taking the first row we see that Marquez came second in Qatar
(QAT), first in Argentina, retired in Austin, and so on. In the first
column, we see the result from Qatar (QAT) in which Marquez came
second, Dovizioso first, Vinales third, and so on. Notation used also
includes six different classes of no-score such as “Ret” for retired,
“WD” for withdrawn, and so on. I now use package function
ordertable2supp(), that translates data of this type into a
log-likelihood. In the package, object moto is the corresponding
Plackett-Luce likelihood function; we drop the final column which is
the points scored by each rider.
moto <- ordertable2supp(moto_table[,-ncol(moto_table)])
head(moto)
## Warning in print.hyper2(x): powers have nonzero sum
## log(A_Espargaro^14 * (A_Espargaro + Abraham + Bagnaia + Bradl + Crutchlow + Dovizioso + Guintoli + Iannone
## + Kallio + Lecuona + Lorenzo + Marquez + Miller + Mir + Morbidelli + Nakagami + Oliveira + P_Espargaro +
## Petrucci + Pirro + Quartararo + Rabat + Rins + Rossi + Smith + Syahrin + Vinales + Zarco)^-19 *
## (A_Espargaro + Abraham + Bagnaia + Bradl + Crutchlow + Dovizioso + Guintoli + Iannone + Kallio + Lecuona +
## Lorenzo + Marquez + Miller + Mir + Morbidelli + Nakagami + Oliveira + P_Espargaro + Petrucci + Pirro +
## Quartararo + Rabat + Rins + Rossi + Smith + Syahrin + Zarco)^-2 * (A_Espargaro + Abraham + Bagnaia + Bradl
## + Crutchlow + Dovizioso + Guintoli + Iannone + Kallio + Lecuona + Lorenzo + Marquez + Miller + Mir +
## Morbidelli + Nakagami + Oliveira + P_Espargaro + Petrucci + Pirro + Quartararo + Rabat + Rossi + Smith +
## Syahrin + Vinales + Zarco)^-2 * (A_Espargaro + Abraham + Bagnaia + Bradl + Crutchlow + Dovizioso + Guintoli
## + Iannone + Kallio + Lecuona + Lorenzo + Marquez + Miller + Mir + Morbidelli + Nakagami + Oliveira +
## P_Espargaro + Petrucci + Pirro + Quartararo + Rabat + Smith + Syahrin + Vinales + Zarco)^-1 * (A_Espargaro
## + Abraham + Bagnaia + Bradl + Crutchlow + Dovizioso + Guintoli + Iannone + Kallio + Lecuona + Lorenzo +
## Marquez + Miller + Mir + Morbidelli + Nakagami + Oliveira + P_Espargaro + Pirro + Quartararo + Rabat + Rins
## + Rossi + Smith + Syahrin + Vinales + Zarco)^-1)
Above, we see a small part of the Placket-Luce likelihood function for
the 2019 results. We can find the maximum likelihood estimator by
using the maxp() function:
moto_maxp <- maxp(moto)
moto_maxp
## A_Espargaro Abraham Bagnaia Bradl Crutchlow Dovizioso Guintoli Iannone Kallio Lecuona
## 2.0089e-02 1.6014e-02 1.5682e-02 3.8040e-03 2.8787e-02 1.1266e-01 3.4048e-03 1.5649e-02 3.7095e-03 1.0119e-06
## Lorenzo Marquez Miller Mir Morbidelli Nakagami Oliveira P_Espargaro Petrucci Pirro
## 1.4637e-02 3.3127e-01 3.3520e-02 2.3260e-02 2.3510e-02 2.2356e-02 1.8844e-02 3.1716e-02 5.7184e-02 8.6998e-04
## Quartararo Rabat Rins Rossi Smith Syahrin Vinales Zarco
## 3.9398e-02 1.3085e-02 5.0789e-02 4.0858e-02 1.7252e-03 1.3677e-02 5.1917e-02 1.1591e-02
dotchart(moto_maxp,pch=16)
Figure 1: Dot chart of riders’ strengths
pie(moto_maxp)
Figure 2: Pie chart of riders’ strengths
In figures 1 and 2, note the dominance of Marquez. It is sometimes preferable to plot the estimated strengths on a log scale:
dotchart(log10(moto_maxp),pch=16)
Figure 3: Dot chart of riders’ strengths, log scale
(in figure @ref(fig:dotchartlogmoto ) observe that the bottom-ranked player, Lecuona, has a ML strength of zero but the estimate is slightly positive for numerical reasons).
Following lines create moto.rda, residing in the data/ directory
of the package.
save(moto,moto_table,moto_maxp,file="moto.rda")