Day 019 — 分散・標準偏差・外れ値(分析編)

2026-04-28 白 / Phase 1 分析 分散・標準偏差・外れ値

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

外れ値とは何か?

外れ値(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
])

タスク:

  1. このデータの 平均・中央値・標準偏差 を計算し、差異から外れ値の存在を推測せよ
  2. IQR法 で外れ値の上限・下限を計算し、外れ値となる値を特定せよ
  3. Zスコア法 で |Z| > 3 となる値を特定せよ
  4. 外れ値を除いた場合と含めた場合の 平均の差 を確認し、外れ値の影響を定量化せよ
  5. この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 解説

1
平均と中央値の差で外れ値を発見する

平均49,118円 vs 中央値3,950円 → 45,000円以上の差!これは典型的な「右裾が重い」分布のサイン。大きな値(850,000円)が平均を引き上げている。

2
IQR法で境界を計算する
  • Q1(下位25%)= 3,125円、Q3(上位75%)= 4,575円
  • IQR = 1,450円
  • 上限 = 4,575 + 1.5×1,450 = 6,750円 → 850,000円はこれを大きく超える
3
Zスコアで「何標準偏差離れているか」を確認する

Zスコア = 4.30 → 平均から4.3標準偏差離れている。3を超えたら外れ値の目安。

4
外れ値の影響を定量化する

外れ値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「確率の基礎(確率とは何か)」

🎯 自己評価

自分の回答

気づき・メモ