if (!require(tidyverse)) {
install.packages("tidyverse")
library(tidyverse)
}
if (!require(patchwork)) {
install.packages("patchwork")
library(patchwork)
}
if (!require(plotly)) {
install.packages("plotly")
library(plotly)
}
if (!require(datapasta)) {
install.packages("datapasta")
library(datapasta)
}
if (!require(rnaturalearth)) {
install.packages("rnaturalearth")
library(rnaturalearth)
}
if (!require(rnaturalearthdata)) {
install.packages("rnaturalearthdata")
library(rnaturalearthdata)
}
if (!require(sf)) {
install.packages("sf")
library(sf)
}
fide_ratings_september <- readr::read_csv(
'https://raw.githubusercontent.com/rfordatascience/tidytuesday/main/data/2025/2025-09-23/fide_ratings_september.csv'
) %>%
arrange(fed, desc = T)
df <- fide_ratings_september |>
filter(!is.na(title)) %>%
filter(title == "GM" | title == "WGM")
#soucrce https://www.mark-weeks.com/aboutcom/mw15b16.html
# datapasta::df_paste()
countries <- data.frame(
stringsAsFactors = FALSE,
Fed = c(
"AFG",
"AHO",
"ALB",
"ALG",
"AND",
"ANG",
"ARG",
"ARM",
"ARU",
"AUS",
"AUT",
"AZE",
"BAH",
"BAN",
"BAR",
"BDI",
"BEL",
"BER",
"BHU",
"BIH",
"BIZ",
"BLR",
"BOL",
"BOT",
"BRA",
"BRN",
"BRU",
"BUL",
"BUR",
"CAF",
"CAM",
"CAN",
"CGO",
"CHI",
"CHN",
"CIV",
"CMR",
"COL",
"COM",
"CRC",
"CRO",
"CUB",
"CYP",
"CZE",
"DEN",
"DJI",
"DOM",
"ECU",
"EGY",
"ENG",
"ESA",
"ESP",
"EST",
"ETH",
"FAI",
"FID",
"FIJ",
"FIN",
"FRA",
"GAB",
"GAM",
"GCI",
"GEO",
"GER",
"GHA",
"GRE",
"GUA",
"GUM",
"GUY",
"HAI",
"HKG",
"HON",
"HUN",
"INA",
"IND",
"IRI",
"IRL",
"IRQ",
"ISL",
"ISR",
"ISV",
"ITA",
"IVB",
"JAM",
"JCI",
"JOR",
"JPN",
"KAZ",
"KEN",
"KGZ",
"KOR",
"KSA",
"KUW",
"LAO",
"LAT",
"LBA",
"LES",
"LIB",
"LIE",
"LTU",
"LUX",
"MAC",
"MAD",
"MAR",
"MAS",
"MAW",
"MDA",
"MDV",
"MEX",
"MGL",
"MKD",
"MLI",
"MLT",
"MNC",
"MNE",
"MOZ",
"MRI",
"MTN",
"MYA",
"NAM",
"NCA",
"NED",
"NEP",
"NGR",
"NOR",
"NZL",
"OMA",
"PAK",
"PAN",
"PAR",
"PER",
"PHI",
"PLE",
"PLW",
"PNG",
"POL",
"POR",
"PUR",
"QAT",
"ROU",
"RSA",
"RUS",
"RWA",
"SCO",
"SEN",
"SEY",
"SIN",
"SLE",
"SLO",
"SMR",
"SOL",
"SOM",
"SRB",
"SRI",
"STP",
"SUD",
"SUI",
"SUR",
"SVK",
"SWE",
"SWZ",
"SYR",
"TAN",
"THA",
"TJK",
"TKM",
"TLS",
"TOG",
"TPE",
"TTO",
"TUN",
"TUR",
"UAE",
"UGA",
"UKR",
"URU",
"USA",
"UZB",
"VEN",
"VIE",
"WLS",
"YEM",
"ZAM",
"ZIM"
),
Country = c(
"Afghanistan",
"Netherlands Antilles",
"Albania",
"Algeria",
"Andorra",
"Angola",
"Argentina",
"Armenia",
"Aruba",
"Australia",
"Austria",
"Azerbaijan",
"Bahamas",
"Bangladesh",
"Barbados",
"Burundi",
"Belgium",
"Bermuda",
"Bhutan",
"Bosnia & Herzegovina",
"Belize",
"Belarus",
"Bolivia",
"Botswana",
"Brazil",
"Bahrain",
"Brunei Darussalam",
"Bulgaria",
"Burinka Faso",
"Central African Republic",
"Cambodia",
"Canada",
"Congo",
"Chile",
"China",
"Cote d'Ivoire",
"Cameroon",
"Colombia",
"Comoros Islands",
"Costa Rica",
"Croatia",
"Cuba",
"Cyprus",
"Czech Republic",
"Denmark",
"Djibouti",
"Dominican Republic",
"Ecuador",
"Egypt",
"United Kingdom",
"El Salvador",
"Spain",
"Estonia",
"Ethiopia",
"Faroe Islands",
"FIDE",
"Fiji",
"Finland",
"France",
"Gabon",
"Gambia",
"Guernsey",
"Georgia",
"Germany",
"Ghana",
"Greece",
"Guatemala",
"Guam",
"Guyana",
"Haiti",
"Hong Kong",
"Honduras",
"Hungary",
"Indonesia",
"India",
"Iran",
"Ireland",
"Iraq",
"Iceland",
"Israel",
"US Virgin Islands",
"Italy",
"British Virgin Islands",
"Jamaica",
"Jersey",
"Jordan",
"Japan",
"Kazakhstan",
"Kenya",
"Kyrgyzstan",
"South Korea",
"Saudi Arabia",
"Kuwait",
"Laos",
"Latvia",
"Libya",
"Lesotho",
"Lebanon",
"Liechtenstein",
"Lithuania",
"Luxembourg",
"Macau",
"Madagascar",
"Morocco",
"Malaysia",
"Malawi",
"Moldova",
"Maldives",
"Mexico",
"Mongolia",
"Former YUG Rep of Macedonia",
"Mali",
"Malta",
"Monaco",
"Montenegro",
"Mozambique",
"Mauritius",
"Mauritania",
"Myanmar",
"Namibia",
"Nicaragua",
"Netherlands",
"Nepal",
"Nigeria",
"Norway",
"New Zealand",
"Oman",
"Pakistan",
"Panama",
"Paraguay",
"Peru",
"Philippines",
"Palestine",
"Palau",
"Papua New Guinea",
"Poland",
"Portugal",
"Puerto Rico",
"Qatar",
"Romania",
"South Africa",
"Russia",
"Rwanda",
"United Kingdom",
"Senegal",
"Seychelles",
"Singapore",
"Sierra Leone",
"Slovenia",
"San Marino",
"Solomon Islands",
"Somalia",
"Serbia",
"Sri Lanka",
"Sao Tome and Principe",
"Sudan",
"Switzerland",
"Suriname",
"Slovakia",
"Sweden",
"Swaziland",
"Syria",
"Tanzania",
"Thailand",
"Tajikistan",
"Turkmenistan",
"Timor-Leste",
"Togo",
"Chinese Taipei",
"Trinidad & Tobago",
"Tunisia",
"Turkey",
"United Arab Emirates",
"Uganda",
"Ukraine",
"Uruguay",
"United States of America",
"Uzbekistan",
"Venezuela",
"Vietnam",
"United Kingdom",
"Yemen",
"Zambia",
"Zimbabwe"
),
C = c(
3L,
2L,
1L,
4L,
1L,
4L,
2L,
1L,
2L,
3L,
1L,
1L,
2L,
3L,
2L,
4L,
1L,
2L,
3L,
1L,
2L,
1L,
2L,
4L,
2L,
3L,
3L,
1L,
4L,
4L,
3L,
2L,
4L,
2L,
3L,
4L,
4L,
2L,
4L,
2L,
1L,
2L,
1L,
1L,
1L,
4L,
2L,
2L,
4L,
1L,
2L,
1L,
1L,
4L,
1L,
0L,
3L,
1L,
1L,
4L,
4L,
1L,
1L,
1L,
4L,
1L,
2L,
3L,
2L,
2L,
3L,
2L,
1L,
3L,
3L,
3L,
1L,
3L,
1L,
1L,
2L,
1L,
2L,
2L,
1L,
3L,
3L,
3L,
4L,
3L,
3L,
3L,
3L,
3L,
1L,
4L,
4L,
3L,
1L,
1L,
1L,
3L,
4L,
4L,
3L,
4L,
1L,
3L,
2L,
3L,
1L,
4L,
1L,
1L,
1L,
4L,
4L,
4L,
3L,
4L,
2L,
1L,
3L,
4L,
1L,
3L,
3L,
3L,
2L,
2L,
2L,
3L,
3L,
3L,
3L,
1L,
1L,
2L,
3L,
1L,
4L,
1L,
4L,
1L,
4L,
4L,
3L,
4L,
1L,
1L,
3L,
4L,
1L,
3L,
4L,
4L,
1L,
2L,
1L,
1L,
4L,
3L,
4L,
3L,
3L,
3L,
3L,
4L,
3L,
2L,
4L,
1L,
3L,
4L,
1L,
2L,
2L,
3L,
2L,
3L,
1L,
3L,
4L,
4L
),
Z = c(
2L,
3L,
5L,
1L,
10L,
3L,
5L,
5L,
3L,
6L,
2L,
8L,
3L,
2L,
3L,
2L,
1L,
3L,
3L,
2L,
3L,
8L,
4L,
3L,
4L,
1L,
3L,
4L,
3L,
4L,
3L,
2L,
3L,
5L,
5L,
4L,
4L,
3L,
3L,
3L,
2L,
3L,
10L,
4L,
3L,
1L,
3L,
3L,
2L,
1L,
3L,
1L,
7L,
2L,
10L,
NA,
6L,
3L,
1L,
4L,
4L,
10L,
5L,
2L,
4L,
5L,
3L,
6L,
3L,
3L,
3L,
3L,
4L,
3L,
7L,
1L,
1L,
1L,
3L,
2L,
3L,
1L,
3L,
3L,
10L,
1L,
3L,
4L,
2L,
4L,
3L,
1L,
1L,
3L,
7L,
1L,
3L,
1L,
10L,
7L,
10L,
3L,
3L,
1L,
3L,
3L,
8L,
3L,
3L,
3L,
2L,
1L,
10L,
10L,
5L,
3L,
3L,
1L,
3L,
3L,
3L,
1L,
2L,
4L,
3L,
6L,
1L,
2L,
3L,
5L,
4L,
3L,
1L,
6L,
6L,
4L,
1L,
3L,
1L,
4L,
3L,
6L,
3L,
1L,
1L,
2L,
3L,
4L,
2L,
10L,
6L,
2L,
5L,
2L,
4L,
2L,
2L,
3L,
4L,
3L,
3L,
1L,
2L,
3L,
4L,
4L,
3L,
4L,
5L,
3L,
1L,
5L,
1L,
2L,
9L,
5L,
1L,
4L,
3L,
3L,
1L,
1L,
3L,
3L
),
S = c(
NA,
"b",
"a",
NA,
NA,
NA,
NA,
"b",
"c",
NA,
"a",
NA,
"a",
NA,
"a",
NA,
"b",
"a",
NA,
"b",
"2",
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
"b",
NA,
"c",
"b",
"a",
NA,
NA,
NA,
NA,
"a",
"b",
NA,
"a",
"c",
"c",
NA,
NA,
NA,
NA,
NA,
NA,
"b",
NA,
NA,
NA,
"b",
"a",
NA,
"a",
"c",
NA,
"b",
"a",
NA,
"c",
NA,
NA,
NA,
NA,
"a",
NA,
NA,
"b",
"a",
"c",
"a",
"a",
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
"c",
NA,
"b",
NA,
NA,
NA,
"a",
NA,
NA,
NA,
NA,
NA,
"c",
"b",
NA,
NA,
NA,
NA,
NA,
NA,
"c",
NA,
NA,
NA,
NA,
NA,
NA,
NA,
"c",
"a",
NA,
NA,
NA,
NA,
NA,
"a",
NA,
NA,
NA,
NA,
"a",
NA,
NA,
NA,
"a",
NA,
NA,
NA,
"a",
"b",
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
NA,
"b",
NA,
"a",
NA,
NA,
NA,
NA,
NA,
NA,
"c",
NA,
"a",
NA,
NA,
NA
),
FIDE.ID = c(
117L,
75L,
47L,
79L,
69L,
101L,
1L,
133L,
159L,
32L,
16L,
134L,
104L,
102L,
111L,
203L,
2L,
88L,
175L,
144L,
0L,
135L,
33L,
113L,
21L,
112L,
105L,
29L,
0L,
0L,
0L,
26L,
0L,
34L,
86L,
208L,
164L,
44L,
0L,
65L,
145L,
35L,
59L,
3L,
14L,
0L,
64L,
36L,
106L,
4L,
67L,
22L,
45L,
157L,
72L,
0L,
114L,
5L,
6L,
106L,
211L,
107L,
136L,
46L,
126L,
42L,
73L,
310L,
197L,
119L,
60L,
84L,
7L,
71L,
50L,
125L,
25L,
48L,
23L,
28L,
68L,
8L,
27L,
74L,
156L,
81L,
70L,
137L,
108L,
138L,
132L,
215L,
103L,
0L,
116L,
92L,
213L,
53L,
120L,
128L,
40L,
154L,
131L,
90L,
57L,
205L,
139L,
167L,
51L,
49L,
150L,
198L,
56L,
54L,
165L,
148L,
97L,
196L,
130L,
152L,
61L,
10L,
123L,
85L,
15L,
43L,
220L,
78L,
66L,
37L,
38L,
52L,
115L,
166L,
91L,
11L,
19L,
31L,
121L,
12L,
143L,
41L,
160L,
24L,
199L,
98L,
58L,
178L,
146L,
118L,
179L,
161L,
9L,
99L,
169L,
122L,
13L,
82L,
149L,
17L,
207L,
76L,
100L,
62L,
147L,
140L,
0L,
212L,
163L,
77L,
55L,
63L,
93L,
100L,
141L,
30L,
20L,
142L,
39L,
124L,
18L,
94L,
87L,
110L
)
) %>%
select(Fed, Country) %>%
rename(fed = Fed)
master <- df %>%
left_join(countries, by = "fed") %>%
relocate(Country, .after = "fed") %>%
arrange(Country, desc. = T) %>%
filter(!is.na(Country))
counts <- master %>%
group_by(Country) %>%
summarise(n = n())
#counts
world <- ne_countries(scale = "medium", returnclass = "sf")
world_masters <- world %>%
left_join(counts, by = c("name" = "Country")) %>%
mutate(
`Number of Masters` = cut(
n,
breaks = c(0, 5, 20, 50, 100, Inf),
labels = c("0–5", "6–20", "21–50", "51–100", "100+"),
include.lowest = TRUE
)
)
p <- ggplot(world_masters) +
geom_sf(aes(
fill = `Number of Masters`,
text = paste0("Country: ", name, "\nActual Number of Grand Masters: ", n)
)) +
scale_fill_brewer(palette = "YlOrRd", na.value = "grey90") +
labs(
fill = "Grandmasters per Country",
title = "Chess Grandmasters per country",
subtitle = "As of September 2025",
caption = "Source: FIDE ratings (Sept 2025)"
) +
theme_minimal() +
theme(axis.text = element_blank(), panel.grid = element_blank())
# Convert to interactive plot
ggplotly(p)