1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

olympicAthletesデータセットの紹介

1
Posted at

たまたま見つけたデータセットを、なんとなくTwitter(現X)に投稿したら意外と反響があったので、少し詳しく紹介してみようと思います。

このデータセットは1896年のアテネ大会から2026年のミラノ・コルティナ大会までの近代オリンピックにおける参加選手と参加競技、メダル獲得状況、各大会のメタデータなどを含んでいます。

CRANに登録されているのでインストールは1行でOKです。

install.packages("olympicAthletes")

3つの主要データフレーム

このデータセットはいくつかのデータフレームを含みますが、主要なのは以下の3つです。

  • olympic_athletes
    • 選手ごとのデータ。選手 × 大会 × 種目。315,094行、16変数。
  • medal_table
    • 国ごとのメダル獲得数一覧。大会 × 国 x チーム。1,929行、11変数。
  • editions
    • 大会ごとのメタデータ。62行、15変数。各大会(中止となった大会を含む)ごとに1行ずつ、参加者数、NOC数、メダル種目数、競技種目数に加え、開会式・閉会式の日程。

まずはこの3つのデータについてEDA(Exploratory Data Analysis、探索的データ分析)をしていきましょう。

まずは基本的なパッケージを呼び出します。

library(conflicted) #関数名の衝突防止
library(tidyverse) #モダンなR
library(olympicAthletes) #今回のテーマとなるデータセット

olympic_athletes

このパッケージの核となる選手ごとのデータです。
各変数の定義は以下です。

  • id: 整数型。選手固有のID。名前だけだと同姓同名の区別がつかないが、このid番号は別になる。
  • name: 文字列型。ASCII変換済みの選手名。
  • sex: 文字列型。性別。"M"か"F"。
  • age: 整数型。生年月日から算出した、大会開始時点のおおよその年齢(冬季は2月1日、夏季は7月15日を基準とする)。
  • height: 数値型。身長(cm)。
  • weight: 数値型。体重(kg)。
  • team: 文字列型。国名またはチーム名。
  • NOC: 文字列型。3文字のIOCコード(例:"USA"、"NOR"、"ROC")。
  • games: 文字列型。"<year> <Summer/Winter>"(例: "2026 Winter")。
  • year: 整数。大会が開催される暦年。東京2020は2021年に開催されたものの、2020とコード化される(IOCの慣例)。
  • season: 文字列型。"Summer"または"Winter"。
  • city_local_latin: 文字列型。現地語表記の開催都市名をラテン文字で表記したもの。
  • city_english: 文字列型。開催都市の一般的な英語名(例:"Athens", "Munich", "Moscow", "Mexico City")。
  • sport: 文字列列型。競技名。(例:"Athletics"、"Gymnastics"、"Swimming")
  • event: 文字列型。スポーツの接頭辞を含むイベント名。(例: Athletics Men's Marathon、Athletics Men's 100 metres)
  • medal: 文字列型。"Gold", "Silver", "Bronze"。メダルを獲得したチームの登録メンバー全員について、そのチームのメダルが記載された行が1つずつ作成される。メダルを獲得していない場合は"NA"になる点に注意。
data(olympic_athletes)
olympic_athletes |>
  glimpse()
# Rows: 315,094
# Columns: 16
# $ id               <int> 12068, 35094, 35698, 38123, 41160, 57441, 68911, 120917, …
# $ name             <chr> "Arthur Charles Blake", "Angelos Fetsis", "Edwin Harold \…
# $ sex              <chr> "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M…
# $ age              <int> 24, NA, 22, 23, 21, NA, 21, 18, 21, 23, 21, 21, NA, 23, N…
# $ height           <dbl> NA, NA, NA, 154, NA, NA, NA, NA, 183, 176, 179, 188, NA, …
# $ weight           <dbl> NA, NA, NA, 45, NA, NA, NA, NA, 66, 66, 73, 102, NA, NA, …
# $ team             <chr> "United States", "Greece", "Australia", "Germany", "Greec…
# $ noc              <chr> "USA", "GRE", "AUS", "GER", "GRE", "GRE", "FRA", "GRE", "…
# $ games            <chr> "1896 Summer", "1896 Summer", "1896 Summer", "1896 Summer…
# $ year             <int> 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 189…
# $ season           <chr> "Summer", "Summer", "Summer", "Summer", "Summer", "Summer…
# $ city_local_latin <chr> "Athína", "Athína", "Athína", "Athína", "Athína", "Athína…
# $ city_english     <chr> "Athens", "Athens", "Athens", "Athens", "Athens", "Athens…
# $ sport            <chr> "Athletics", "Athletics", "Athletics", "Athletics", "Athl…
# $ event            <chr> "Athletics Men's 1,500 metres", "Athletics Men's 1,500 me…
# $ medal            <chr> "Silver", NA, "Gold", NA, NA, NA, "Bronze", NA, "Gold", N…

summaryToolsパッケージを使うとデータセットの全体像を把握しやすいです。

library(summarytools)

olympic_athletes |>
  dfSummary() |>
  summarytools::view()

olympic_athletes.jpg

注意!

olympic_athletesデータは意外と難易度が高いデータです。扱ううえでいくつか注意が必要です。

  1. 重複する行が多くある
  2. 欠測値がある。特にheight, weightに多い。
  3. 同姓同名の選手がいる。idが個人ごとにユニークなので、idを使えば問題ない。
  4. 同じ選手が複数の競技に参加すると複数行になる。

データ生成上の問題だと思いますが、完全に同じ行が612件あります。使う前にユニークな行に絞る必要があります。

olympic_athletes |>
   summarise(n = n(), .by = !id) |>
   dplyr::filter(n > 1) |>
   glimpse()
# Rows: 612
# Columns: 16
# $ name             <chr> "Henri Leclerc", "Jean-Baptiste tienne August Charcot",…
# $ sex              <chr> "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", …
# $ age              <int> NA, 23, NA, 28, NA, 34, NA, NA, 40, NA, NA, 30, NA, 34,…
# $ height           <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
# $ weight           <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
# $ team             <chr> "France", "Quand-Mme-2", "Plume-Patte-5", "Quand-Mme-2"…
# $ noc              <chr> "FRA", "FRA", "FRA", "FRA", "FRA", "FRA", "FRA", "FRA",…
# $ games            <chr> "1900 Summer", "1900 Summer", "1900 Summer", "1900 Summ…
# $ year             <int> 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1…
# $ season           <chr> "Summer", "Summer", "Summer", "Summer", "Summer", "Summ…
# $ city_local_latin <chr> "Paris", "Paris", "Paris", "Paris", "Paris", "Paris", "…
# $ city_english     <chr> "Paris", "Paris", "Paris", "Paris", "Paris", "Paris", "…
# $ sport            <chr> "Equestrianism", "Sailing", "Sailing", "Sailing", "Sail…
# $ event            <chr> "Equestrianism Mixed Jumping, Individual", "Sailing Mix…
# $ medal            <chr> NA, "Silver", NA, "Silver", NA, NA, "Silver", "Silver",…
# $ n                <int> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…

distinct()でユニークな行に絞りましょう。

olympic_athletes_unique <- olympic_athletes |>
  distinct()

欠測値の状況を確認します。これはnaniarパッケージを使うと便利です。
欠測の組み合わせを確認します。

library(naniar)

olympic_athletes_unique |>
  select(!medal) |>
  gg_miss_upset()

Rplot.png

身長と体重の値が同時に結束しているケースが多いようです。
欠測にはMCAR、MAR、MNARなどいくつかのパターンがあり、それによって対処法も変わってきます。
開催年毎に見ると1960年代から2010年代にかけての時期で欠測が多いようです。

library(scales)
olympic_athletes_unique |>
  distinct(id, games, .keep_all = TRUE) |> #1つの大会で複数の競技に参加している選手などを1行にまとめる処理
    summarise(
    across(c(height, weight), \(x) mean(is.na(x))),
    .by = c(year, season)
  ) |>
  pivot_longer(c(height, weight), names_to = "変数", values_to = "欠損率") |>
  ggplot(aes(year, 欠損率, color = 変数)) +
  geom_line(linewidth = 0.8) +
  geom_point(size = 1.2) +
  facet_wrap(vars(season)) +
  scale_y_continuous(labels = percent_format()) +
  labs(
    title = "身長と体重の欠損率の推移(選手×大会単位)",
    x = "開催年", y = "欠損率", color = NULL
  )

Rplot01.png
特定の年代に欠測が偏っているのでMCARではなさそうです。観測データだけではMNARか否かは判断が難しく、実務的にはMARとして扱っていいでしょう。

最後に同姓同名のケースです。

same_name <- olympic_athletes_unique |>
  distinct(id, name) |>
  count(name)

same_name |>
  dplyr::filter(n > 1) |>
  tally()
# n
# 1 713

713組! 意外と多いですね!
どんな名前が多いんでしょうか?

same_name |>
  slice_max(n, n=5)
#             name n
# 1    Ivan Ivanov 5
# 2  Kim Seong-Eun 5
# 3         Li Jie 5
# 4      Lszl Szab 5
# 5       Wang Nan 5
# 6 Wolfgang Mller 5
# 7       Zhang Li 5

同姓同名が5人いるケースが7組も!

5人のIvan Ivanov選手はどんな人たちか確認してみましょう。

olympic_athletes_unique |>
  dplyr::filter(name == "Ivan Ivanov") |>
  distinct(id, team, sport)
#      id         team      sport
# 1 52808 Soviet Union  Athletics
# 2 52802     Bulgaria Volleyball
# 3 52812   Kyrgyzstan   Swimming
# 4 52805     Bulgaria  Wrestling
# 5 52810   Kazakhstan  Athletics

ソ連の陸上選手、ブルガリアのバレーボール選手、キルギスの水泳選手、ブルガリアのレスリング選手、カザフスタンの陸上選手、の5人でした。

medal_table

国ごとのメダル獲得数のデータです。大会 × 国。チーム単位の競技におけるメダル数を集計したい場合はこちらのデータセットを使ってください。例えば、アイスホッケーで金メダルを獲得したチームはメダルを1つとしてカウントします。各選手が受け取ったメダルを合計して25個とはしません。

data(medal_table)
medal_table |>
  glimpse()
# Rows: 1,929
# Columns: 11
# $ edition_id <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
# $ games      <chr> "1896 Summer", "1896 Summer", "1896 Summer", "1896 Summer", "18…
# $ year       <int> 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 1896, 189…
# $ season     <chr> "Summer", "Summer", "Summer", "Summer", "Summer", "Summer", "Su…
# $ noc        <chr> "USA", "GRE", "GER", "FRA", "GBR", "HUN", "AUT", "AUS", "DEN", …
# $ country    <chr> "United States", "Greece", "Germany", "France", "Great Britain"…
# $ gold       <int> 11, 10, 6, 5, 2, 2, 2, 2, 1, 1, 1, 31, 20, 20, 6, 6, 4, 3, 1, 1…
# $ silver     <int> 7, 18, 5, 4, 3, 1, 1, 0, 2, 2, 0, 41, 13, 8, 6, 3, 3, 2, 3, 2, …
# $ bronze     <int> 2, 19, 2, 2, 2, 3, 2, 0, 3, 0, 1, 40, 15, 9, 6, 1, 2, 0, 2, 3, …
# $ total      <int> 20, 47, 13, 11, 7, 6, 5, 2, 6, 3, 2, 112, 48, 37, 18, 10, 9, 5,…
# $ notes      <chr> "", "", "", "", "", "", "", "", "", "", "Mixed-NOC team (athlet…

これもsummaryToolsで全体像を把握しましょう。

medal_table |>
  dfSummary() |>
  summarytools::view()

medal_table.jpg

editions

大会ごとのメタデータです。
注意として、1956 Summerのみメルボルン本会場とストックホルム馬術会場の2行に分かれているので、他のデータフレームとjoinするときは、事前に2行を統合する必要があります。

editions |>
  glimpse()
# Rows: 62
# Columns: 15
# $ edition_id       <int> 1, 2, 3, 4, 5, 6, 50, 7, 8, 29, 9, 30, 10, 31, 11, 32, 5…
# $ games            <chr> "1896 Summer", "1900 Summer", "1904 Summer", "1906 Summe…
# $ year             <int> 1896, 1900, 1904, 1906, 1908, 1912, 1916, 1920, 1924, 19…
# $ season           <chr> "Summer", "Summer", "Summer", "Summer", "Summer", "Summe…
# $ city_local_latin <chr> "Athína", "Paris", "St. Louis", "Athína", "London", "Sto…
# $ city_english     <chr> "Athens", "Paris", "St. Louis", "Athens", "London", "Sto…
# $ country          <chr> "Greece", "France", "United States", "Greece", "Great Br…
# $ opening_ceremony <date> 1896-04-06, NA, 1904-05-14, 1906-04-22, 1908-07-13, 191…
# $ closing_ceremony <date> 1896-04-15, NA, NA, 1906-05-02, 1908-07-25, 1912-07-15,…
# $ participants     <int> 176, 1241, 650, 841, 2024, 2409, NA, 2680, 3255, 312, 32…
# $ nocs             <int> 13, 26, 10, 21, 23, 28, NA, 29, 45, 19, 46, 25, 47, 17, …
# $ medal_events     <int> 43, 95, 95, 74, 110, 107, NA, 162, 131, 17, 125, 14, 131…
# $ disciplines      <int> 10, 22, 18, 14, 24, 23, NA, 33, 27, 10, 24, 8, 26, 7, 31…
# $ notes            <chr> "", "", "", "Intercalated Games; not officially recognis…
# $ source           <chr> "https://www.olympedia.org/editions/1", "https://www.oly…

これもsummaryToolsで。

editions |>
  dfSummary() |>
  summarytools::view()

editions.jpg

以上です。

何か面白い分析のアイデアがあったら、ぜひ記事にして公開してください。

Enjoy!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?