I will use the cleaned chess tournament data from Project 1 and compare each player’s pre-tournament rating with the ratings of their opponents. For each matchup, I will calculate the player’s expected Elo score and then add the expected scores across all games, to then compare the total expected score with the player’s actual tournament points. Finally, I will sort the differences to identify the five players who most overperformed and the five players who most underperformed expectations.
Introduction
This assignment builds on the chess tournament data used in Project 1. The goal is to calculate each player’s expected tournament score using the Elo rating system and compare it with the player’s actual tournament points. The difference between actual and expected performance will then be used to identify the five players who most over-performed and the five players who most under-performed.
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.2.1 ✔ readr 2.2.0
✔ forcats 1.0.1 ✔ stringr 1.6.0
✔ ggplot2 4.0.3 ✔ tibble 3.3.1
✔ lubridate 1.9.5 ✔ tidyr 1.3.2
✔ purrr 1.2.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Warning in readLines(tournament_url): incomplete final line found on
'https://raw.githubusercontent.com/yeimiperez14/Data_607/main/Project%201/tournamentinfo.txt'
# A tibble: 6 × 10
player_number player_name total_points round1 round2 round3 round4 round5
<dbl> <chr> <dbl> <chr> <chr> <chr> <chr> <chr>
1 1 GARY HUA 6 W 39 W 21 W 18 W 14 W 7
2 2 DAKSHESH DARURI 6 W 63 W 58 L 4 W 17 W 16
3 3 ADITYA BAJAJ 6 L 8 W 61 W 25 W 21 W 11
4 4 PATRICK H SCHIL… 5.5 W 23 D 28 W 2 W 26 D 5
5 5 HANSHI ZUO 5.5 W 45 W 37 D 12 D 13 D 4
6 6 HANSEN SONG 5 W 34 D 29 L 11 W 35 D 10
# ℹ 2 more variables: round6 <chr>, round7 <chr>
# A tibble: 6 × 11
player_number player_name total_points round1 round2 round3 round4 round5
<dbl> <chr> <dbl> <chr> <chr> <chr> <chr> <chr>
1 1 GARY HUA 6 W 39 W 21 W 18 W 14 W 7
2 2 DAKSHESH DARURI 6 W 63 W 58 L 4 W 17 W 16
3 3 ADITYA BAJAJ 6 L 8 W 61 W 25 W 21 W 11
4 4 PATRICK H SCHIL… 5.5 W 23 D 28 W 2 W 26 D 5
5 5 HANSHI ZUO 5.5 W 45 W 37 D 12 D 13 D 4
6 6 HANSEN SONG 5 W 34 D 29 L 11 W 35 D 10
# ℹ 3 more variables: round6 <chr>, round7 <chr>, pre_rating <dbl>
players %>%filter(player_name =="GARY HUA")
# A tibble: 1 × 11
player_number player_name total_points round1 round2 round3 round4 round5
<dbl> <chr> <dbl> <chr> <chr> <chr> <chr> <chr>
1 1 GARY HUA 6 W 39 W 21 W 18 W 14 W 7
# ℹ 3 more variables: round6 <chr>, round7 <chr>, pre_rating <dbl>
Changing the 7 round columns into rows
games <- players %>%pivot_longer(cols = round1:round7,names_to ="round",values_to ="round_result" )
head(games, 10)
# A tibble: 10 × 6
player_number player_name total_points pre_rating round round_result
<dbl> <chr> <dbl> <dbl> <chr> <chr>
1 1 GARY HUA 6 1794 round1 W 39
2 1 GARY HUA 6 1794 round2 W 21
3 1 GARY HUA 6 1794 round3 W 18
4 1 GARY HUA 6 1794 round4 W 14
5 1 GARY HUA 6 1794 round5 W 7
6 1 GARY HUA 6 1794 round6 D 12
7 1 GARY HUA 6 1794 round7 D 4
8 2 DAKSHESH DARURI 6 1553 round1 W 63
9 2 DAKSHESH DARURI 6 1553 round2 W 58
10 2 DAKSHESH DARURI 6 1553 round3 L 4
Extract the result code
games <- games %>%mutate(result_code =str_extract( round_result,"^[A-Z]" ) )
head(games)
# A tibble: 6 × 7
player_number player_name total_points pre_rating round round_result
<dbl> <chr> <dbl> <dbl> <chr> <chr>
1 1 GARY HUA 6 1794 round1 W 39
2 1 GARY HUA 6 1794 round2 W 21
3 1 GARY HUA 6 1794 round3 W 18
4 1 GARY HUA 6 1794 round4 W 14
5 1 GARY HUA 6 1794 round5 W 7
6 1 GARY HUA 6 1794 round6 D 12
# ℹ 1 more variable: result_code <chr>
Extracting the opponents number
games <- games %>%mutate(opponent_number =as.numeric(str_extract(round_result, "\\d+") ) )
head(games)
# A tibble: 6 × 8
player_number player_name total_points pre_rating round round_result
<dbl> <chr> <dbl> <dbl> <chr> <chr>
1 1 GARY HUA 6 1794 round1 W 39
2 1 GARY HUA 6 1794 round2 W 21
3 1 GARY HUA 6 1794 round3 W 18
4 1 GARY HUA 6 1794 round4 W 14
5 1 GARY HUA 6 1794 round5 W 7
6 1 GARY HUA 6 1794 round6 D 12
# ℹ 2 more variables: result_code <chr>, opponent_number <dbl>
Remove rounds without an Opponent
played_games <- games %>%filter(!is.na(opponent_number))
Those rounds do not contain an opponent number, so there is no opponent rating available for an Elo calculation.
I am using total_points here because the assignment asks to compare expected score with the player’s actual tournament score.
Some players have special rounds such as B or H, for which there is no rated opponent. Those rounds therefore do not generate an Elo expected value, as that limitation comes from the structure of the tournament file itself.
The performance difference was calculated by subtracting each player’s Elo expected score from the player’s actual tournament score. Positive differences indicate that the player scored more points than expected based on the ratings of their opponents, while negative differences indicate that the player scored fewer points than expected.
Conclusion
The Elo calculations provided a way to compare each player’s actual tournament performance with the performance expected from the rating differences between the player and their opponents. After calculating and summing the expected scores, the difference between actual and expected performance was used to identify the five greatest over-performers and five greatest underperformers in the tournament.