Day 003 — 記述統計入門(平均・中央値・最頻値)

2026-04-11 白 / Phase 1 分析 記述統計入門(平均・中央値・最頻値)

📚 背景知識(読んでから問題へ)

「データの代表値」には3種類あります。どれを使うかで、データの見え方がガラッと変わります。

  • 平均(Mean): 全員を同じ高さにならしたときの値。外れ値(極端な値)に引っ張られやすい
  • 中央値(Median): データを小さい順に並べたとき、ちょうど真ん中の値。外れ値に強い
  • 最頻値(Mode): 最も多く出てくる値。カテゴリデータ(性別・血液型など)で特に有効

実生活の例: 年収データで「平均年収」が高く見えるのは、一部の超高収入者が引き上げているため。「中央値」のほうが「普通の人の年収」に近い。


📝 問題

以下のTitanicデータを分析してください。

import pandas as pd
import numpy as np

# Titanicデータの一部
data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Hank', 'Ivy', 'Jack'],
    'Pclass': [1, 3, 2, 1, 3, 3, 2, 1, 3, 2],
    'Age': [29, 22, 35, 42, 18, 25, 33, 55, 20, np.nan],
    'Fare': [211.3, 7.9, 26.0, 263.0, 7.9, 8.1, 13.0, 512.3, 7.8, 26.0],
    'Survived': [1, 0, 1, 1, 0, 0, 1, 1, 0, 1]
}
df = pd.DataFrame(data)

以下の問いに答えてください:

  1. Fare(運賃)の平均・中央値・最頻値を計算してください
  2. 平均と中央値の差が大きい場合、それは何を意味しているか説明してください
  3. Pclass(客室クラス: 1=一等, 2=二等, 3=三等)の最頻値を求め、このデータで最も多いクラスを答えてください
  4. Ageに欠損値(NaN)がありますが、平均で補完した場合と中央値で補完した場合、どちらが望ましいか、理由とともに答えてください

🔍 ヒント(段階的開示)

ヒント1(方向性)

pandasのSeriesには統計を計算するメソッドが揃っています。それぞれのメソッドを使い分けましょう。

ヒント2(アプローチ)
  • 平均: .mean()
  • 中央値: .median()
  • 最頻値: .mode()[0](リストで返るので[0]で最初の値を取る)
  • 欠損補完: .fillna(値)
ヒント3(コード骨格)
# 1. Fareの統計
fare_mean = df['Fare'].___()
fare_median = df['Fare'].___()
fare_mode = df['Fare'].___()[0]

# 3. Pclassの最頻値
pclass_mode = df['Pclass'].___()[0]

# 4. Ageの補完
df['Age_mean_filled'] = df['Age'].fillna(df['Age'].___())
df['Age_median_filled'] = df['Age'].fillna(df['Age'].___())

模範解答

import pandas as pd
import numpy as np

data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Hank', 'Ivy', 'Jack'],
    'Pclass': [1, 3, 2, 1, 3, 3, 2, 1, 3, 2],
    'Age': [29, 22, 35, 42, 18, 25, 33, 55, 20, np.nan],
    'Fare': [211.3, 7.9, 26.0, 263.0, 7.9, 8.1, 13.0, 512.3, 7.8, 26.0],
    'Survived': [1, 0, 1, 1, 0, 0, 1, 1, 0, 1]
}
df = pd.DataFrame(data)

# 1. Fareの統計
fare_mean   = df['Fare'].mean()     # 約 108.43
fare_median = df['Fare'].median()   # 19.5
fare_mode   = df['Fare'].mode()[0]  # 7.9(最多登場)

print(f"Fare 平均: {fare_mean:.2f}")
print(f"Fare 中央値: {fare_median:.2f}")
print(f"Fare 最頻値: {fare_mode:.2f}")

# 3. Pclassの最頻値
pclass_mode = df['Pclass'].mode()[0]
print(f"\nPclass 最頻値: {pclass_mode} (三等客室が最多)")

# 4. Ageの補完
df['Age_mean_filled']   = df['Age'].fillna(df['Age'].mean())
df['Age_median_filled'] = df['Age'].fillna(df['Age'].median())

print(f"\nAge 平均補完: {df['Age_mean_filled'].values}")
print(f"Age 中央値補完: {df['Age_median_filled'].values}")

出力例:

▶ 出力を見る
Fare 平均: 108.43
Fare 中央値: 19.50
Fare 最頻値: 7.90

Pclass 最頻値: 3 (三等客室が最多)

Age 平均補完: [29. 22. 35. 42. 18. 25. 33. 55. 20. 28.56]
Age 中央値補完: [29. 22. 35. 42. 18. 25. 33. 55. 20. 27. ]

🪜 Step-by-Step 解説

1
Fareの平均と中央値を比較する
fare_mean   = df['Fare'].mean()    # 108.43
fare_median = df['Fare'].median()  # 19.50

平均108.43 vs 中央値19.50 — 大きな差があります。

なぜ差がでるか?

HankのFare=512.3(一等客の最高運賃)が平均を大きく引き上げているためです。

中央値は「512.3という外れ値」の影響を受けません。

差が大きい = 外れ値(極端な値)が存在するサイン

2
最頻値でカテゴリを調べる
pclass_mode = df['Pclass'].mode()[0]  # 3

mode()はリストを返すため[0]で最初の値を取ります。

(同率最多が複数ある場合に備えてリスト形式になっています)

3
欠損値補完の判断
df['Age_mean_filled']   = df['Age'].fillna(df['Age'].mean())    # 28.56で補完
df['Age_median_filled'] = df['Age'].fillna(df['Age'].median())  # 27.0で補完

どちらが望ましいか?

補完方法特徴
平均補完28.56外れ値(高齢者・子供)に引っ張られる
中央値補完27.0外れ値に強い、より「典型的な値」

Ageデータには外れ値(幼児や高齢者)が含まれやすいため、中央値補完が一般的に望ましい


📐 数学・統計の補足(文系向け)

なぜ平均は外れ値に弱いのか?

たとえば [10, 10, 10, 10, 1000] というデータ:

  • 平均 = (10×4 + 1000) ÷ 5 = 208 ← 実態とかけ離れている
  • 中央値 = 10 ← 「だいたいこのくらい」という実感に近い

Kaggleのデータでも「価格」「年収」「アクセス数」などは外れ値が多く、中央値・対数変換が有効です。


🏆 Kaggleでの実践的な使い方

場面使う代表値
欠損値の補完(数値データ)外れ値が少ない → 平均 / 多い → 中央値
欠損値の補完(カテゴリデータ)最頻値
分布の歪みチェック平均 > 中央値 → 右に歪んでいる(高額品など)
特徴量の要約統計df.describe() で一括確認

実際のコンペでよく見るコード:

# 欠損補完のベストプラクティス
df['Age'].fillna(df['Age'].median(), inplace=True)          # 数値→中央値
df['Embarked'].fillna(df['Embarked'].mode()[0], inplace=True)  # カテゴリ→最頻値

⚠️ よくある誤解・ミス

誤解・ミスなぜ起こるか正しい理解
mode()の結果を直接使うmode()はSeriesを返すmode()[0]でスカラー値を取得
常に平均で欠損補完する平均が「普通の値」と思い込む外れ値の有無を確認してから選ぶ
平均≒中央値と思い込む正規分布を前提にしてしまう歪んだ分布では大きく異なる

🚀 次のステップ

  • 発展: 歪度(Skewness)を計算し、分布の形を定量化する(df['Fare'].skew()
  • 次回予告: テーマ2「分散・標準偏差・外れ値」— データのばらつきを数値で表す方法

🎯 自己評価

自分の回答

気づき・メモ