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

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

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

標準偏差とは?(直感的理解)

「平均からどれくらいズレているか」の平均的な大きさ。

例えばテストで、クラスの平均点が70点のとき:

  • Aクラス: 全員68〜72点 → 標準偏差が小さい(みんな似たスコア)
  • Bクラス: 40点〜100点がバラバラ → 標準偏差が大きい(散らばりが大きい)

外れ値とは?

他のデータと比べて極端に大きい/小さい値。

外れ値を放置するとモデルの精度が下がる ため、発見と対処が重要。

外れ値の検出方法

  1. IQR法(四分位範囲): データの中央50%の範囲(IQR)を計算し、その1.5倍を超えるものを外れ値とみなす
  • 下限: Q1 - 1.5 × IQR
  • 上限: Q3 + 1.5 × IQR
  1. Zスコア法: 平均から何標準偏差離れているか。|Zスコア| > 3 なら外れ値
  • Z = (値 - 平均) / 標準偏差

📝 問題

以下のデータは、あるECサイトの「1日の注文件数」を20日間記録したものです。

import numpy as np
import pandas as pd

orders = pd.Series([
    45, 52, 48, 51, 49,
    47, 53, 50, 46, 48,
    52, 49, 51, 47, 50,
    48, 200, 45, 53, 1  # 200と1が含まれている
])

次の分析タスクを行ってください:

  1. 平均、中央値、標準偏差を求める
  2. 外れ値を IQR法 で検出し、外れ値のインデックスと値を出力する
  3. 外れ値を除いた後の平均・中央値・標準偏差と比較し、「外れ値が与える影響」を日本語でコメントとして記述する
  4. ボックスプロット(箱ひげ図)を描いて外れ値を視覚的に確認する

🔍 ヒント(段階的開示)

ヒント1(方向性)

まず基本統計量を求め、次にIQRを計算して外れ値の上限/下限を求めます。その後、外れ値を除外したデータと比べましょう。

ヒント2(アプローチ)
  • orders.describe() で基本統計量が一気に確認できます
  • IQR = Q3 - Q1 (quantile(0.75) - quantile(0.25))
  • ボックスプロットは plt.boxplot() または seaborn.boxplot() で描ける
ヒント3(コード骨格)
# 基本統計量
mean = orders.mean()
median = orders.median()
std = orders.std()

# 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 = orders[(orders < lower) | (orders > upper)]

# 外れ値除外後
clean = orders[(orders >= lower) & (orders <= upper)]

模範解答

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

orders = pd.Series([
    45, 52, 48, 51, 49,
    47, 53, 50, 46, 48,
    52, 49, 51, 47, 50,
    48, 200, 45, 53, 1
])

# --- 1. 基本統計量 ---
print("=== 全データ ===")
print(f"平均:         {orders.mean():.2f}")
print(f"中央値:       {orders.median():.2f}")
print(f"標準偏差:     {orders.std():.2f}")

# --- 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

print(f"\n=== IQR法 ===")
print(f"Q1={Q1}, Q3={Q3}, IQR={IQR}")
print(f"外れ値の範囲: [{lower:.1f}, {upper:.1f}]")

outliers = orders[(orders < lower) | (orders > upper)]
print(f"\n外れ値:\n{outliers}")

# --- 3. 外れ値除外後の比較 ---
clean = orders[(orders >= lower) & (orders <= upper)]

print("\n=== 外れ値除外後 ===")
print(f"平均:     {clean.mean():.2f}")
print(f"中央値:   {clean.median():.2f}")
print(f"標準偏差: {clean.std():.2f}")

# コメント
# 平均は 200(高い外れ値)と 1(低い外れ値)に大きく引っ張られるが、
# 中央値はほとんど変化しない。
# → 外れ値が存在する場合、平均より中央値の方が「代表値」として信頼できる。

# --- 4. ボックスプロット ---
fig, axes = plt.subplots(1, 2, figsize=(10, 4))
axes[0].boxplot(orders, vert=True)
axes[0].set_title("全データ(外れ値あり)")
axes[0].set_ylabel("1日の注文件数")

axes[1].boxplot(clean, vert=True)
axes[1].set_title("外れ値除外後")
axes[1].set_ylabel("1日の注文件数")

plt.tight_layout()
plt.savefig("boxplot_orders.png")
plt.show()
print("ボックスプロットを保存しました。")

出力例:

▶ 出力を見る
=== 全データ ===
平均:         53.35
中央値:       49.50
標準偏差:     39.37

=== IQR法 ===
Q1=47.25, Q3=51.75, IQR=4.50
外れ値の範囲: [40.5, 58.5]

外れ値:
16    200
19      1
dtype: int64

=== 外れ値除外後 ===
平均:     49.39
中央値:   49.00
標準偏差:  2.55

🪜 Step-by-Step 解説

1
基本統計量で全体像をつかむ

orders.mean()orders.median() を比較する。外れ値がある場合、平均 > 中央値 になる(正の歪み)か 平均 < 中央値(負の歪み)になる。今回は200という大きい外れ値があるため平均が中央値より高い。

2
IQRで外れ値の境界を計算する

IQR(四分位範囲)= Q3 - Q1。この1.5倍を超えたら外れ値とみなす。

今回: IQR = 51.75 - 47.25 = 4.5

  • 下限: 47.25 - 6.75 = 40.5
  • 上限: 51.75 + 6.75 = 58.5

→ 200と1の両方が外れ値と判定される

3
外れ値除外後の変化を確認する
  • 平均: 53.35 → 49.39(大きく変化)
  • 中央値: 49.50 → 49.00(ほぼ変化なし)
  • 標準偏差: 39.37 → 2.55(劇的に変化)

標準偏差は外れ値に非常に敏感。データの「ばらつき」を論じる前に外れ値チェックが必須。

4
ボックスプロットで視覚確認

箱(ボックス)の上下端がQ3/Q1、中の線が中央値、ひげ(whisker)の外の点が外れ値として表示される。視覚的に一瞬で外れ値の位置がわかる。


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

なぜ1.5倍なのか?

正規分布(ベルカーブ)に従うデータでは、IQRの1.5倍の外側に入るデータは全体の約0.7%しかない。つまり「100個のうち1個未満しか出ない珍しい値」を外れ値と定義している。(2.0や3.0倍を使うこともある)

IQR法 vs Zスコア法

  • IQR法: 中央値・四分位数を使うので外れ値の影響を受けにくい(ロバスト)
  • Zスコア法: 平均・標準偏差を使うので外れ値が多いと検出精度が落ちる

外れ値があるかもしれない時はIQR法が推奨


🏆 Kaggleでの実践的な使い方

  • House Prices コンペ: 住宅価格に超高額物件(外れ値)が含まれることがある。外れ値を除去 or log変換することで線形モデルの精度が上がる
  • log変換の活用: np.log1p(price) で価格データの歪みを補正するテクニックはKaggle上位解で頻出
  • 外れ値の除去 or 維持: 「本物の異常値(データ入力ミス)」は除去。「自然に起きる稀な出来事」は維持すべきケースもある

⚠️ よくある誤解・ミス

誤解・ミスなぜ起こるか正しい理解
外れ値は常に削除すべき「ノイズ」と思い込む外れ値が重要な情報の場合もある(詐欺検出など)
平均だけで代表値を判断平均を「普通」と思い込む外れ値があれば中央値の方が信頼できる
標準偏差が大きい = データが悪い直感的誤解外れ値があるだけかもしれない。まず外れ値チェックを

🚀 次のステップ

  • 発展: scipy.stats.zscore() でZスコア法による外れ値検出を実装する
  • 次回予告: 確率の基礎(確率とは何か・条件付き確率)

🎯 自己評価

自分の回答

気づき・メモ