library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.4.3
## Warning: package 'ggplot2' was built under R version 4.4.3
## Warning: package 'dplyr' was built under R version 4.4.3
library(openintro)
## Warning: package 'openintro' was built under R version 4.4.3

packages installation

#install.packages("janitor")  

I was looking for a simple dataset with count data for chess players transfer to the U.S.

library(readr)

# Option 1: Double backslashes
chess_df <- read_csv('https://raw.githubusercontent.com/tanzil64/Tanzil_Tidyverse/refs/heads/main/chess_transfers.csv')
## Rows: 932 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): url, Federation, Form.Fed, Transfer Date
## dbl (1): ID
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Preview the data
#glimpse(chess_df)
str(chess_df)
## spc_tbl_ [932 × 5] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ url          : chr [1:932] "https://ratings.fide.com/fedchange.phtml?year=2000" "https://ratings.fide.com/fedchange.phtml?year=2000" "https://ratings.fide.com/fedchange.phtml?year=2000" "https://ratings.fide.com/fedchange.phtml?year=2000" ...
##  $ ID           : num [1:932] 2019221 14401754 14401762 2019221 14401754 ...
##  $ Federation   : chr [1:932] "USA" "BIH" "BIH" "USA" ...
##  $ Form.Fed     : chr [1:932] "PHI" "CRO" "YUG" "PHI" ...
##  $ Transfer Date: chr [1:932] "12/15/00" "1/31/00" "1/31/00" "12/15/00" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   url = col_character(),
##   ..   ID = col_double(),
##   ..   Federation = col_character(),
##   ..   Form.Fed = col_character(),
##   ..   `Transfer Date` = col_character()
##   .. )
##  - attr(*, "problems")=<externalptr>
# Clean column names
chess_df <- chess_df %>%
  janitor::clean_names()

# View cleaned column names
names(chess_df)
## [1] "url"           "id"            "federation"    "form_fed"     
## [5] "transfer_date"
# Extract year from date
chess_df <- chess_df %>%
  mutate(
    parsed_date = parse_date_time(transfer_date, orders = c("ymd", "dmy", "mdy")),
    transfer_year = year(parsed_date)
  )

# Count transfers per year
transfers_per_year <- chess_df %>%
  count(transfer_year)

chess_df <- chess_df %>% 
  filter(!is.na(form_fed) & !is.na(form_fed))
str(chess_df)
## tibble [923 × 7] (S3: tbl_df/tbl/data.frame)
##  $ url          : chr [1:923] "https://ratings.fide.com/fedchange.phtml?year=2000" "https://ratings.fide.com/fedchange.phtml?year=2000" "https://ratings.fide.com/fedchange.phtml?year=2000" "https://ratings.fide.com/fedchange.phtml?year=2000" ...
##  $ id           : num [1:923] 2019221 14401754 14401762 2019221 14401754 ...
##  $ federation   : chr [1:923] "USA" "BIH" "BIH" "USA" ...
##  $ form_fed     : chr [1:923] "PHI" "CRO" "YUG" "PHI" ...
##  $ transfer_date: chr [1:923] "12/15/00" "1/31/00" "1/31/00" "12/15/00" ...
##  $ parsed_date  : POSIXct[1:923], format: "2000-12-15" "2000-01-31" ...
##  $ transfer_year: num [1:923] 2000 2000 2000 2000 2000 ...

Visualization: Transfers Over Time

ggplot(transfers_per_year, aes(x = transfer_year, y = n)) +
  geom_line(color = "blue", size = 1) +
  geom_point(color = "darkred", size = 2) +
  labs(title = "Chess Player Transfers Over Time",
       x = "Year",
       y = "Number of Transfers") +
  theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Most Active Federations

# Count transfers out by 'form_fed' and select top 10
top_federations <- chess_df %>%
  count(form_fed, sort = TRUE) %>%
  slice_max(n, n = 10)

ggplot(top_federations, aes(x = reorder(form_fed, n), y = n)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  coord_flip() +
  labs(title = "Top 10 Federations by Transfers Out",
       x = "From Federation",
       y = "Number of Transfers") +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
    axis.text = element_text(size = 12)
  )

## Sorting by Number of Transfers

chess_df %>% 
  count(form_fed) %>% 
  ggplot(aes(x = fct_reorder(form_fed, n), y = n)) +
  geom_col(fill = "lightblue") +
  labs(x = "Destination Federation", 
       y = "Number of Transfers", 
       caption = "Data: FIDE Federation Transfers") +
  coord_flip()

## Grouping Less Frequent Federations

top_feds <- chess_df %>% 
  count(form_fed) %>% 
  arrange(desc(n)) %>% 
  slice_head(n = 5) %>% 
  pull(form_fed)

chess_df %>% 
  count(form_fed) %>% 
  mutate(form_fed = fct_other(form_fed, keep = top_feds, other_level = "Other Federations")) %>% 
  group_by(form_fed) %>% 
  summarise(n = sum(n)) %>% 
  ggplot(aes(x = fct_reorder(form_fed, n), y = n)) +
  geom_col(fill = "lightblue") +
  labs(x = "Destination Federation", 
       y = "Number of Transfers", 
       caption = "Data: FIDE Federation Transfers") +
  coord_flip()

chess_df %>% 
  count(form_fed) %>% 
  mutate(form_fed = fct_other(form_fed, keep = top_feds, other_level = "Other Federations")) %>% 
  group_by(form_fed) %>% 
  summarise(n = sum(n)) %>% 
  ggplot(aes(x = fct_reorder(form_fed, n), y = n)) +
  geom_col(fill = "lightblue") +
  labs(x = "Destination Federation", 
       y = "Number of Transfers", 
       title = "Top Chess Federation Transfer Destinations",
       subtitle = paste0(min(chess_df$transfer_year), "-", max(chess_df$transfer_year)),
       caption = "Data: FIDE Federation Transfers") +
  theme(plot.title = element_text(size = 18, color = "blue"),
        plot.subtitle = element_text(size = 14, color = "gold")) +
  coord_flip()

LS0tDQp0aXRsZTogIlRhbnppbCBUaWR5dmVyc2UiDQphdXRob3I6ICJNZC4gVGFuemlsIEVoc2FuIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiBvcGVuaW50cm86OmxhYl9yZXBvcnQNCi0tLQ0KDQpgYGB7ciBsb2FkLXBhY2thZ2VzLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KG9wZW5pbnRybykNCmBgYA0KDQoNCg0KDQojIHBhY2thZ2VzIGluc3RhbGxhdGlvbg0KDQpgYGB7cn0NCiNpbnN0YWxsLnBhY2thZ2VzKCJqYW5pdG9yIikgIA0KDQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQoNCmxpYnJhcnkobWFncml0dHIpICAgIyBmb3IgJT4lDQpsaWJyYXJ5KGphbml0b3IpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZm9yY2F0cykNCmxpYnJhcnkoZ3QpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGphbml0b3IpDQpgYGANCkkgd2FzIGxvb2tpbmcgZm9yIGEgc2ltcGxlIGRhdGFzZXQgd2l0aCBjb3VudCBkYXRhIGZvciBjaGVzcyBwbGF5ZXJzIHRyYW5zZmVyIHRvIHRoZSBVLlMuDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KHJlYWRyKQ0KDQojIE9wdGlvbiAxOiBEb3VibGUgYmFja3NsYXNoZXMNCmNoZXNzX2RmIDwtIHJlYWRfY3N2KCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vdGFuemlsNjQvVGFuemlsX1RpZHl2ZXJzZS9yZWZzL2hlYWRzL21haW4vY2hlc3NfdHJhbnNmZXJzLmNzdicpDQoNCiMgUHJldmlldyB0aGUgZGF0YQ0KI2dsaW1wc2UoY2hlc3NfZGYpDQpgYGANCmBgYHtyfQ0Kc3RyKGNoZXNzX2RmKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDbGVhbiBjb2x1bW4gbmFtZXMNCmNoZXNzX2RmIDwtIGNoZXNzX2RmICU+JQ0KICBqYW5pdG9yOjpjbGVhbl9uYW1lcygpDQoNCiMgVmlldyBjbGVhbmVkIGNvbHVtbiBuYW1lcw0KbmFtZXMoY2hlc3NfZGYpDQpgYGANCg0KYGBge3J9DQojIEV4dHJhY3QgeWVhciBmcm9tIGRhdGUNCmNoZXNzX2RmIDwtIGNoZXNzX2RmICU+JQ0KICBtdXRhdGUoDQogICAgcGFyc2VkX2RhdGUgPSBwYXJzZV9kYXRlX3RpbWUodHJhbnNmZXJfZGF0ZSwgb3JkZXJzID0gYygieW1kIiwgImRteSIsICJtZHkiKSksDQogICAgdHJhbnNmZXJfeWVhciA9IHllYXIocGFyc2VkX2RhdGUpDQogICkNCg0KIyBDb3VudCB0cmFuc2ZlcnMgcGVyIHllYXINCnRyYW5zZmVyc19wZXJfeWVhciA8LSBjaGVzc19kZiAlPiUNCiAgY291bnQodHJhbnNmZXJfeWVhcikNCg0KY2hlc3NfZGYgPC0gY2hlc3NfZGYgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKGZvcm1fZmVkKSAmICFpcy5uYShmb3JtX2ZlZCkpDQpgYGANCmBgYHtyfQ0Kc3RyKGNoZXNzX2RmKQ0KYGBgDQojIyBWaXN1YWxpemF0aW9uOiBUcmFuc2ZlcnMgT3ZlciBUaW1lDQpgYGB7cn0NCmdncGxvdCh0cmFuc2ZlcnNfcGVyX3llYXIsIGFlcyh4ID0gdHJhbnNmZXJfeWVhciwgeSA9IG4pKSArDQogIGdlb21fbGluZShjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEpICsNCiAgZ2VvbV9wb2ludChjb2xvciA9ICJkYXJrcmVkIiwgc2l6ZSA9IDIpICsNCiAgbGFicyh0aXRsZSA9ICJDaGVzcyBQbGF5ZXIgVHJhbnNmZXJzIE92ZXIgVGltZSIsDQogICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICB5ID0gIk51bWJlciBvZiBUcmFuc2ZlcnMiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KDQoNCiMjICBNb3N0IEFjdGl2ZSBGZWRlcmF0aW9ucw0KYGBge3J9DQojIENvdW50IHRyYW5zZmVycyBvdXQgYnkgJ2Zvcm1fZmVkJyBhbmQgc2VsZWN0IHRvcCAxMA0KdG9wX2ZlZGVyYXRpb25zIDwtIGNoZXNzX2RmICU+JQ0KICBjb3VudChmb3JtX2ZlZCwgc29ydCA9IFRSVUUpICU+JQ0KICBzbGljZV9tYXgobiwgbiA9IDEwKQ0KDQpnZ3Bsb3QodG9wX2ZlZGVyYXRpb25zLCBhZXMoeCA9IHJlb3JkZXIoZm9ybV9mZWQsIG4pLCB5ID0gbikpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic3RlZWxibHVlIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKHRpdGxlID0gIlRvcCAxMCBGZWRlcmF0aW9ucyBieSBUcmFuc2ZlcnMgT3V0IiwNCiAgICAgICB4ID0gIkZyb20gRmVkZXJhdGlvbiIsDQogICAgICAgeSA9ICJOdW1iZXIgb2YgVHJhbnNmZXJzIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpDQogICkNCg0KDQpgYGANCiMjIFNvcnRpbmcgYnkgTnVtYmVyIG9mIFRyYW5zZmVycw0KYGBge3J9DQpjaGVzc19kZiAlPiUgDQogIGNvdW50KGZvcm1fZmVkKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IGZjdF9yZW9yZGVyKGZvcm1fZmVkLCBuKSwgeSA9IG4pKSArDQogIGdlb21fY29sKGZpbGwgPSAibGlnaHRibHVlIikgKw0KICBsYWJzKHggPSAiRGVzdGluYXRpb24gRmVkZXJhdGlvbiIsIA0KICAgICAgIHkgPSAiTnVtYmVyIG9mIFRyYW5zZmVycyIsIA0KICAgICAgIGNhcHRpb24gPSAiRGF0YTogRklERSBGZWRlcmF0aW9uIFRyYW5zZmVycyIpICsNCiAgY29vcmRfZmxpcCgpDQpgYGANCiMjIEdyb3VwaW5nIExlc3MgRnJlcXVlbnQgRmVkZXJhdGlvbnMNCmBgYHtyfQ0KdG9wX2ZlZHMgPC0gY2hlc3NfZGYgJT4lIA0KICBjb3VudChmb3JtX2ZlZCkgJT4lIA0KICBhcnJhbmdlKGRlc2MobikpICU+JSANCiAgc2xpY2VfaGVhZChuID0gNSkgJT4lIA0KICBwdWxsKGZvcm1fZmVkKQ0KDQpjaGVzc19kZiAlPiUgDQogIGNvdW50KGZvcm1fZmVkKSAlPiUgDQogIG11dGF0ZShmb3JtX2ZlZCA9IGZjdF9vdGhlcihmb3JtX2ZlZCwga2VlcCA9IHRvcF9mZWRzLCBvdGhlcl9sZXZlbCA9ICJPdGhlciBGZWRlcmF0aW9ucyIpKSAlPiUgDQogIGdyb3VwX2J5KGZvcm1fZmVkKSAlPiUgDQogIHN1bW1hcmlzZShuID0gc3VtKG4pKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IGZjdF9yZW9yZGVyKGZvcm1fZmVkLCBuKSwgeSA9IG4pKSArDQogIGdlb21fY29sKGZpbGwgPSAibGlnaHRibHVlIikgKw0KICBsYWJzKHggPSAiRGVzdGluYXRpb24gRmVkZXJhdGlvbiIsIA0KICAgICAgIHkgPSAiTnVtYmVyIG9mIFRyYW5zZmVycyIsIA0KICAgICAgIGNhcHRpb24gPSAiRGF0YTogRklERSBGZWRlcmF0aW9uIFRyYW5zZmVycyIpICsNCiAgY29vcmRfZmxpcCgpDQpgYGANCg0KYGBge3J9DQpjaGVzc19kZiAlPiUgDQogIGNvdW50KGZvcm1fZmVkKSAlPiUgDQogIG11dGF0ZShmb3JtX2ZlZCA9IGZjdF9vdGhlcihmb3JtX2ZlZCwga2VlcCA9IHRvcF9mZWRzLCBvdGhlcl9sZXZlbCA9ICJPdGhlciBGZWRlcmF0aW9ucyIpKSAlPiUgDQogIGdyb3VwX2J5KGZvcm1fZmVkKSAlPiUgDQogIHN1bW1hcmlzZShuID0gc3VtKG4pKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IGZjdF9yZW9yZGVyKGZvcm1fZmVkLCBuKSwgeSA9IG4pKSArDQogIGdlb21fY29sKGZpbGwgPSAibGlnaHRibHVlIikgKw0KICBsYWJzKHggPSAiRGVzdGluYXRpb24gRmVkZXJhdGlvbiIsIA0KICAgICAgIHkgPSAiTnVtYmVyIG9mIFRyYW5zZmVycyIsIA0KICAgICAgIHRpdGxlID0gIlRvcCBDaGVzcyBGZWRlcmF0aW9uIFRyYW5zZmVyIERlc3RpbmF0aW9ucyIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAobWluKGNoZXNzX2RmJHRyYW5zZmVyX3llYXIpLCAiLSIsIG1heChjaGVzc19kZiR0cmFuc2Zlcl95ZWFyKSksDQogICAgICAgY2FwdGlvbiA9ICJEYXRhOiBGSURFIEZlZGVyYXRpb24gVHJhbnNmZXJzIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCwgY29sb3IgPSAiYmx1ZSIpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiZ29sZCIpKSArDQogIGNvb3JkX2ZsaXAoKQ0KYGBgDQoNCg0K