前処理の方針#

実装は R/prepare_data.R。ここではその判断の根拠を書く。

生データは既にかなり整っている(tidy で、型もほぼ正しい)。 本当に効いてくるのは型変換ではなく、どの期間・どの粒度なら何が言えるかの線引き。


1. まず決めた 2 つの境界線#

根拠となる実測は データの癖 にまとめた。 ここでは決めたことだけを書く。

1-1. メダルを選手データから数えてよいのは 2016 年まで#

2018 年以降は選手データ側のメダルが 2〜3 割欠けている。

方針: 国別メダル数の分析には medal_table(公式集計)だけを使う。 選手データからメダルを数えるのは MEDAL_ATHLETE_COMPLETE_MAX_YEAR = 2016 まで。

1-2. 身長・体重を使えるのは 1960-2016 年#

height の欠損率は 1950 年代まで 7 割前後、1960 年代に 6% へ急落し、 2018 年以降ふたたび 4〜7 割に戻る。

全期間で「時代とともに選手が大型化した」と言うと、実際には 記録が残った選手の偏りの変化を見ていることになる。

方針: 身体データの分析は BODY_YEARS = c(1960, 2016) に固定する。 この期間で 196,619 行が使える。

1-3. 夏季と冬季は分けて集計する#

参加国数も種目数も桁が違う。合算するとシェアの分母が混ざり、 1994 年以降は開催年が交互になるため時系列がギザギザになる。

方針: メダルと体格の図はすべて season で分ける。


2. クリーニング#

2-1. 完全重複だけを落とす#

(id, games, event) が重複する行が 1,480 行(687 キー)ある。 中身を見ると多くが実在のケースだった:

重複キーの 8 割は 1948 年以前に集中する。

方針: 全 16 列が一致する完全重複 1,385 行のみ distinct() で除去。 (id, games, event) での重複排除はしない(実データを壊す)。 結果 315,094 → 313,709 行。

2-2. medal の NA はメダルなし#

86% が NA だが、これは欠損ではなく「入賞しなかった」を表す。 欠損として扱うとメダリストだけが残る。

方針: medalfactor(levels = c("Gold","Silver","Bronze")) に変換し、 NA のまま保持。is_medalist = !is.na(medal) を派生させる。

2-3. noc の欠損は落とさず、集計時にだけ除く#

noc の欠損 3,907 行はすべて 2018 年以降(team も同時に NA)。 参加や体格の分析では使えるので、行ごと落とすのは損。

方針: 保持したまま、国単位の集計を組み立てる build_event_medals() の中でだけ !is.na(noc) で絞る。

2-4. BMI の外れ値#

weight / (height/100)^2 の生の範囲は 8.4 - 63.9 で、生理的にありえない値を含む (身長体重どちらかの入力誤りと思われる)。

方針: BMI を使う図では 13-45 の範囲に限定する(analysis/04_body_metrics.RBMI_RANGE)。除外は全体の 0.1% 未満。身長・体重を単独で使う分には制限しない。


3. 型変換#

変換 理由
medal chr → factor(Gold, Silver, Bronze) 図の凡例順を金銀銅に固定する
season chr → factor(Summer, Winter) 同上
sex chr → factor(Women, Men) M/F のままだと軸ラベルが読めない

year は int のまま。日付にする意味がない(大会は年単位)。


4. 派生変数#

変数 定義 用途
is_medalist !is.na(medal) メダル獲得の有無
decade 10 * (year %/% 10) 年代別の集計
bmi weight / (height/100)^2 体格の比較
event_gender event 文字列から Women / Mixed / Men を判定 種目構成の分析
lineage, lineage_label NOC の継承関係(下記) 長期の趨勢

event_gender は種目名の約 9 割で判定できる(Women 91,030 / Men 203,739 / Mixed 18,170 / 判定不能 770 行)。"Women" を先に判定すること ("Men" の部分一致で誤判定はしないが、順序を明示しておく)。

種目単位のメダル表 event_medals#

団体競技はメダル 1 個に対して選手行が人数分ある。 1908 年の体操団体は 1 つの金メダルに 38 行が対応する。

athletes |>
  filter(!is.na(medal), !is.na(noc)) |>
  distinct(games, year, season, decade, noc, lineage, lineage_label,
           sport, event, medal)

これで 44,098 行 → 21,299 行。

ただし公式集計と完全一致はしない。 選手データが揃っている 1896-2016 の 51 大会で公式総数と突き合わせると、平均 1.2 件、最大で +7 / −4 件ずれる (1 大会あたり 0.1〜0.2% 程度)。原因は 2 方向ある。

比較の用途には十分な精度だが、メダル数そのものを示す図には使わない (公式 medal_table を使う)。この誤差の測定は tests/check_claims.R で 毎回検証している。

1 種目のメダルが 4 件になるのは正常(2024 夏では 249 種目中 55 種目)。 柔道・ボクシング・レスリング・テコンドーは銅を 2 個授与する。 2016 夏で確認したところ、1 種目あたりのメダル件数は 3 件か 4 件しかなく、 5 件以上になる種目は存在しない。


5. 国の継承関係#

分裂・統合した国を素の NOC のまま扱うと、長期の趨勢で系列が途切れる。

グループ 含む NOC
USSR / Russia URS, EUN, RUS, OAR, ROC
Germany (all) GER, FRG, GDR, EUA, SAA
Czechoslovakia + TCH, CZE, SVK
Yugoslavia + YUG, SCG, SRB

これは粗い集約。東西ドイツを足すのも、チェコとスロバキアを チェコスロバキアの後継として 1 本にするのも、目的次第で妥当性が変わる。 使う図には必ず注記する。

特に注意が要るのは「同じ大会に両方が出場している」期間。 継承関係でまとめると、別々に出場した 2 か国の合計を 1 本の線として 描くことになる。該当するのは次の期間で、年代別シェアの図(medals_era_share.png)の 1970-80 年代の ドイツの山はまさにこれ(単一国の成績ではない)。

グループ 併存している大会 内訳
Germany (all) 1968-1988 の 10 大会 FRG + GDR
Czechoslovakia + 1996 以降の 13 大会 CZE + SVK

単一国として見たい場合は lineage を使わず生の noc で集計する。

AIN(Individual Neutral Athletes, 2024-2026)は意図的にどこにも入れていない。 ロシアとベラルーシの選手が混在しており、片方に寄せると誤りになるため。


6. メダリストと非メダリストを比べるときの標準化#

「メダリストは背が高いか」を競技ごとに素朴に比べると 2 つの理由で誤る。

  1. 種目構成: 陸上のメダリストが背が高く見えるのは、背の高い種目 (走高跳・砲丸投)のメダリストが多く混ざったからかもしれない
  2. 時代: 選手は時代とともに大型化する。メダリストの年代分布が違えば差が出る

そこで身長・体重を 種目 × 性別 × 年代 のセル内で z 化してから比較する (analysis/05_body_medalist_gap.R)。セルは 20 人以上を要求する。

さらに団体競技では、チームがメダルを取ると構成員全員がメダリストになる。 標本は選手ではなく実質チームなので、素の標準誤差は小さく出すぎる。 (大会 × 種目 × NOC) をクラスタとしたクラスタ頑健標準誤差(CR1)を使う。 実測でホッケー 1.8 倍・野球 2.0 倍に膨らむ。

配色と作図上の注意は 開発 にまとめた。


7. 意図的にやっていないこと#