<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/harry-potter-and-rankings-with-comperank/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.questionflow.org/2018/05/31/harry-potter-and-rankings-with-comperank/"> QuestionFlow </a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p> Ranking Harry Potter books with comperank package.</p>
<div>
<h1>Prologue</h1>
<p>Package <a rel="nofollow" href="https://github.com/echasnovski/comperank" target="_blank">comperank</a> is <a rel="nofollow" href="https://cran.r-project.org/package=comperank" target="_blank">on CRAN</a> now. It offers consistent implementations of several ranking and rating methods. Originally, it was intended to be my first CRAN package when I started to build it 13 months ago. Back then I was very curious to learn about different ranking and rating methods that are used in sport. This led me to two conclusions:</p>
<ul>
<li>There is an amazing book <a rel="nofollow" href="https://www.amazon.com/Whos-1-Science-Rating-Ranking/dp/069116231X" target="_blank">“Who’s #1”</a> by Langville and Meyer which describes several ideas in great detail.</li>
<li>Although there are some CRAN packages dedicated specifically to ranking methods (for example, <a rel="nofollow" href="https://cran.r-project.org/package=elo" target="_blank">elo</a>, <a rel="nofollow" href="https://cran.r-project.org/package=mvglmmRank" target="_blank">mvglmmRank</a>), I didn’t find them to be <a rel="nofollow" href="https://cran.r-project.org/web/packages/tidyverse/vignettes/manifesto.html" target="_blank">tidy</a> enough.</li>
</ul>
<p>These discoveries motivated me to write my first ever CRAN package. Things didn’t turn out the way I was planning, and now <code>comperank</code> is actually my fourth. After spending some time writing it I realized that most of the package will be about storing and manipulating competition results in consistent ways. That is how <a rel="nofollow" href="https://echasnovski.github.io/comperes/" target="_blank">comperes</a> was born.</p>
<p>After diverging into creating this site and writing <a rel="nofollow" href="https://echasnovski.github.io/ruler/" target="_blank">ruler</a> in pair with <a rel="nofollow" href="https://echasnovski.github.io/keyholder/" target="_blank">keyholder</a>, a few months ago I returned to competition results and rankings. Gained experience helped me to improve functional API of both packages which eventually resulted into submitting them to CRAN.</p>
</div>
<div>
<h1>Overview</h1>
<p>This post, as <a rel="nofollow" href="http://www.questionflow.org/2018/05/09/harry-potter-and-competition-results-with-comperes/" target="_blank">one of the previous ones</a>, has two goals:</p>
<ul>
<li>Explore different types of rankings on <a rel="nofollow" href="http://www.questionflow.org/2018/04/09/struggle-with-harry-potter-data/" target="_blank">Harry Potter Books Survey</a> results (data provided by <code>comperes</code>).</li>
<li>Demonstrate basic functionality of <code>comperank</code> package. To learn more go to its <a rel="nofollow" href="https://echasnovski.github.io/comperank/index.html" target="_blank">README</a>, <a rel="nofollow" href="https://echasnovski.github.io/comperank/articles/" target="_blank">vignettes</a> and <a rel="nofollow" href="https://echasnovski.github.io/comperank/reference/index.html" target="_blank">manual pages</a>.</li>
</ul>
<p>We will cover the following topics:</p>
<ul>
<li>Short notes about <strong>functionality of comperank</strong>.</li>
<li><strong>Exploration ranking</strong> with ranking based on mean book score. No <code>comperank</code> package functionality is required.</li>
<li><strong>Rankings with fixed Head-to-Head structure</strong>. This will cover Massey and Colley ranking methods.</li>
<li><strong>Rankings with variable Head-to-Head structure</strong>. This will cover Keener, Markov and Offense-Defense ranking methods.</li>
<li><strong>Combined rankings</strong> in which average ranks will be computed using all described <code>comperank</code> methods.</li>
</ul>
<p>Another very interesting set of ranking methods implemented in <code>comperank</code> are methods with iterative nature. However, their usage with mentioned <a rel="nofollow" href="https://echasnovski.github.io/comperes/reference/hp_survey.html" target="_blank">Harry Potter Books Survey dataset</a> is meaningless as temporal ordering of games (acts of book scoring by one person) should make sense, which it doesn’t.</p>
<p>The idea behind converting survey results into competition results is described in aforementioned post. We will need the following setup:</p>
<pre><code>library(dplyr)
library(purrr)
library(rlang)

# This will automatically load {comperes}
library(comperank)

# Create competition results from hp_survey
hp_cr &lt;- hp_survey %>%
  transmute(
    game = person, player = book,
    score = as.integer(gsub(&quot;[^0-9].*$&quot;, &quot;&quot;, score))
  ) %>%
  as_longcr()</code></pre>
</div>
<div>
<h1>Functionality of comperank</h1>
<p><strong>Rating</strong> is considered to be a list (in the ordinary sense) of numerical values, one for each player, or the numerical value itself. Its interpretation depends on rating method: either bigger value indicates better player performance or otherwise.</p>
<p><strong>Ranking</strong> is considered to be a rank-ordered list (in the ordinary sense) of players: rank 1 indicates player with best performance.</p>
<p><code>comperank</code> leverages the <a rel="nofollow" href="https://www.tidyverse.org/" target="_blank">tidyverse</a> ecosystem of R packages. Among other things, it means that the main output format is <a rel="nofollow" href="http://tibble.tidyverse.org/" target="_blank">tibble</a>.</p>
<p>There are three sets of functions:</p>
<ul>
<li><code>rate_*()</code> (<code>*</code> stands for ranking method short name). Its output is a tibble with columns <code>player</code> (player identifier) and at least one <code>rating_*</code> (rating value). Names of rating columns depend on rating method.</li>
<li><code>rank_*()</code>. Its default output is similar to previous one, but with <code>ranking_*</code> instead of rating columns. It runs <code>rate_*()</code> and does ranking with correct direction. One can use option <code>keep_rating = TRUE</code> to keep rating columns in the output.</li>
<li><code>add_*_ratings()</code>. These functions are present only for algorithms with iterative nature and competition results with games only between two players. They return tibble with row corresponding to a game and extra columns indicating ratings of players before and after the game.</li>
</ul>
</div>
<div>
<h1>Exploration ranking</h1>
<p>Previously we established that “Harry Potter and the Prisoner of Azkaban” seems to be “the best” book and “Harry Potter and the Chamber of Secrets” comes last. This was evaluated by mean score:</p>
<pre><code>hp_rank_explore &lt;- hp_cr %>%
  summarise_player(rating_explore = mean(score)) %>%
  # round_rank() is a function from {comperank} package for doing ranking
  mutate(ranking_explore = round_rank(rating_explore))
hp_rank_explore
## # A tibble: 7 x 3
##   player rating_explore ranking_explore
##   </code></pre></div>