📚 背景知識(読んでから問題へ)
外れ値とは何か?
外れ値(Outlier)とは、他のデータから極端に離れた値のことです。
例えば、クラスのテスト平均が65点のとき、「2点」や「99点」の人がいたとします。こういった「普通じゃない値」が外れ値です。
なぜ外れ値が問題になるのか?
外れ値は平均を大きく引っ張る性質があります。
- 月給が全員30万円の会社に、社長だけ3000万円 → 平均が大きく歪む
- 外れ値をそのままにすると、機械学習モデルの精度が落ちる
外れ値の検出方法(2つ覚えれば十分)
①IQR法(四分位範囲)
データを並べて4等分したときの「25%点(Q1)」と「75%点(Q3)」の差がIQR。
外れ値の境界:
- 上限: Q3 + 1.5 × IQR
- 下限: Q1 - 1.5 × IQR
②Zスコア法
「平均からどれだけ標準偏差分離れているか」を数値化。|Z| > 3 が外れ値の目安。
Z = (データ値 - 平均) / 標準偏差
📝 問題
以下のデータはあるECサイトの1日の注文金額(円)です。
import numpy as np
import pandas as pd
orders = pd.Series([
3200, 4500, 2800, 5100, 3900, 4200, 3600,
2950, 4800, 3300, 850000, 4100, 3750, 2600,
4400, 3100, 5500, 2900, 4700, 3800
])
タスク:
- このデータの 平均・中央値・標準偏差 を計算し、差異から外れ値の存在を推測せよ
- IQR法 で外れ値の上限・下限を計算し、外れ値となる値を特定せよ
- Zスコア法 で |Z| > 3 となる値を特定せよ
- 外れ値を除いた場合と含めた場合の 平均の差 を確認し、外れ値の影響を定量化せよ
- このECサイトのコンテキストで、850,000円の注文は「除くべき外れ値」か「残すべき高額注文」か、理由を述べよ
🔍 ヒント(段階的開示)
ヒント1(方向性)
まず平均と中央値を比較する。平均 >> 中央値なら、右側(大きい方向)に外れ値が引っ張っているサイン。
ヒント2(アプローチ)
IQR法: Q1 = orders.quantile(0.25), Q3 = orders.quantile(0.75), IQR = Q3 - Q1
Zスコア: z = (orders - orders.mean()) / orders.std()
ヒント3(コード骨格)
# 1. 基本統計
mean = orders.mean()
median = orders.median()
std = orders.std()
# 2. IQR法
Q1 = orders.quantile(0.25)
Q3 = orders.quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers_iqr = orders[(orders < lower) | (orders > upper)]
# 3. Zスコア法
z_scores = (orders - mean) / std
outliers_z = orders[abs(z_scores) > 3]
# 4. 外れ値の影響
orders_clean = orders[(orders >= lower) & (orders <= upper)]
print(f"外れ値込み平均: {mean:.0f}円")
print(f"外れ値除外後平均: {orders_clean.mean():.0f}円")
✅ 模範解答
import numpy as np
import pandas as pd
orders = pd.Series([
3200, 4500, 2800, 5100, 3900, 4200, 3600,
2950, 4800, 3300, 850000, 4100, 3750, 2600,
4400, 3100, 5500, 2900, 4700, 3800
])
# 1. 基本統計
mean = orders.mean()
median = orders.median()
std = orders.std()
print("=== 基本統計 ===")
print(f"平均: {mean:,.0f}円")
print(f"中央値: {median:,.0f}円")
print(f"標準偏差: {std:,.0f}円")
print(f"→ 平均 - 中央値 = {mean - median:,.0f}円(大きな差は外れ値のサイン)")
# 2. IQR法
print("\n=== IQR法 ===")
Q1 = orders.quantile(0.25)
Q3 = orders.quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
print(f"Q1={Q1:,.0f}, Q3={Q3:,.0f}, IQR={IQR:,.0f}")
print(f"正常範囲: {lower:,.0f}円 〜 {upper:,.0f}円")
outliers_iqr = orders[(orders < lower) | (orders > upper)]
print(f"外れ値(IQR法): {outliers_iqr.values}")
# 3. Zスコア法
print("\n=== Zスコア法 ===")
z_scores = (orders - mean) / std
outliers_z = orders[abs(z_scores) > 3]
print(f"外れ値(|Z|>3): {outliers_z.values}")
print(f"850,000円のZスコア: {z_scores[orders == 850000].values[0]:.2f}")
# 4. 外れ値の影響
print("\n=== 外れ値の影響 ===")
orders_clean = orders[(orders >= lower) & (orders <= upper)]
print(f"外れ値込み平均: {mean:,.0f}円")
print(f"外れ値除外後平均: {orders_clean.mean():,.0f}円")
print(f"差: {mean - orders_clean.mean():,.0f}円({(mean - orders_clean.mean()) / orders_clean.mean() * 100:.1f}%の歪み)")
出力例:
▶ 出力を見る
=== 基本統計 ===
平均: 49,118円
中央値: 3,950円
標準偏差: 186,548円
→ 平均 - 中央値 = 45,168円(大きな差は外れ値のサイン)
=== IQR法 ===
Q1=3,125, Q3=4,575, IQR=1,450
正常範囲: 950円 〜 6,750円
外れ値(IQR法): [850000]
=== Zスコア法 ===
外れ値(|Z|>3): [850000]
850,000円のZスコア: 4.30
=== 外れ値の影響 ===
外れ値込み平均: 49,118円
外れ値除外後平均: 3,934円
差: 45,184円(1148.3%の歪み)Q5の考察(模範例):
850,000円の注文は「除くべき外れ値」か「残すべき高額注文」か、文脈に依存する。
- 除くべきケース: 注文金額の予測モデルを作る場合。平均注文単価を分析する場合。大多数のユーザー行動を把握したい場合。
- 残すべきケース: VIP顧客の行動分析を含む場合。収益分析では高額注文が重要な意味を持つ場合。「高額注文の傾向」自体をモデリングしたい場合。
重要: 外れ値は「機械的に削除」するのではなく、分析の目的に応じて判断する。Kaggleでは外れ値の扱いがスコアに大きく影響することがある。
🪜 Step-by-Step 解説
平均49,118円 vs 中央値3,950円 → 45,000円以上の差!これは典型的な「右裾が重い」分布のサイン。大きな値(850,000円)が平均を引き上げている。
- Q1(下位25%)= 3,125円、Q3(上位75%)= 4,575円
- IQR = 1,450円
- 上限 = 4,575 + 1.5×1,450 = 6,750円 → 850,000円はこれを大きく超える
Zスコア = 4.30 → 平均から4.3標準偏差離れている。3を超えたら外れ値の目安。
外れ値1点が平均を45,000円(1148%)も歪めていた。これがそのままモデルの学習データになると、誤った予測が生まれる。
📐 数学・統計の補足(文系向け)
四分位数(Quartile)とは?
100人のテストの点数を低い順に並べたとき:
- Q1(25番目の人の点数)= 第1四分位数
- Q2(50番目の人の点数)= 中央値
- Q3(75番目の人の点数)= 第3四分位数
IQRは「真ん中の50%のデータが収まる幅」。IQRの1.5倍以上離れたデータが「普通じゃない」とみなす。
🏆 Kaggleでの実践的な使い方
- House Prices コンペ: 住宅価格データに外れ値(異常に高い/低い物件)が含まれる。外れ値をどう扱うかが特徴量エンジニアリングの重要ポイント
- tabular コンペ: EDAの段階で外れ値を可視化し、除外/変換/フラグ化の戦略を決める
- 対数変換: 右裾が重い分布はlog変換で正規分布に近づけることが多い(
np.log1p())
⚠️ よくある誤解・ミス
| 誤解・ミス | なぜ起こるか | 正しい理解 |
|---|---|---|
| 「外れ値は必ず除去する」 | 機械的なデータクリーニングの習慣 | ビジネス文脈で判断する。VIP顧客データは外れ値でも重要 |
| 「平均で外れ値を確認できる」 | 平均が代表値と思い込む | 平均は外れ値に引っ張られる。中央値と比較して初めて気づく |
| IQRとstdの混同 | どちらも「ばらつき」を表すと思う | IQR=中間50%の幅、std=全体の平均からのズレの大きさ |
🚀 次のステップ
- 発展: 外れ値の可視化(boxplot、散布図でどう見えるか確認する)
- 次回予告: Phase 1 テーマ3「確率の基礎(確率とは何か)」