Σ
SDCalc
中級概念·12 min

頑健統計:MAD、IQR、外れ値に強い手法

中央絶対偏差(MAD)と四分位範囲(IQR)を含む頑健統計の完全ガイド。外れ値に強い散布度の指標を使うべき場面を、例とPythonコード付きで解説。

なぜ頑健統計が必要か?

標準偏差は強力な散布度の指標ですが、致命的な弱点があります。外れ値に対する極端な敏感さです。たった1つの極端な値がSDを劇的に膨らませ、典型的なばらつきについて誤った印象を与える可能性があります。

頑健統計は外れ値の影響に耐える散布度の指標を提供します。測定エラー、データ入力ミス、あるいは本物の極端なケースが存在する実世界のデータにおいて不可欠です。

例:外れ値の影響

データ:10, 12, 11, 13, 12, 11, 100(外れ値が1つ) 標準偏差: 32.4(外れ値に支配される) MAD: 1.0(外れ値を無視する) IQR: 1.5(外れ値を無視する)

ブレークダウンポイント

統計量の「ブレークダウンポイント」とは、その統計量が無意味になるまでに極端にできるデータの割合です。SDのブレークダウンポイントは0%(1つの外れ値で破壊される)。MADとIQRのブレークダウンポイントは50%—データの半分が外れ値であっても正しく機能します。

中央絶対偏差(MAD)

MADは最も頑健な散布度の指標です。中央値からの絶対偏差の中央値を計算します。

MADの公式

MAD = median(|xᵢ - median(x)|)
1

中央値を求める

データセットの中央値を計算します。
2

偏差を計算する

各値から中央値を引き、絶対値を取ります。
3

MADを求める

これらの絶対偏差の中央値を計算します。

MADをσの推定に換算: 正規分布データでは、MAD ≈ 0.6745 × σ。MADからSDを推定するには1.4826を掛けます。

MADからのSD推定

σ̂ = 1.4826 × MAD

なぜ1.4826なのか?

このスケーリング係数は、正規分布におけるMADとSDの関係から導かれます。データが正規分布に従う場合、スケーリングされたMADが真の標準偏差の不偏推定量となることを保証します。

四分位範囲(IQR)

IQRはデータの中央50%の散らばり—第25パーセンタイルと第75パーセンタイルの間の範囲—を測定します。

IQRの公式

IQR = Q3 - Q1 = 75th percentile - 25th percentile

IQRは理解しやすく、箱ひげ図で視覚化しやすく、外れ値検出の一般的な「1.5×IQRルール」の基礎となるため、広く使われています。

IQRをσの推定に換算: 正規データでは、IQR ≈ 1.35 × σ。IQRからSDを推定するには:

IQRからのSD推定

σ̂ = IQR / 1.35 ≈ 0.7413 × IQR

頑健指標の比較

標準偏差

すべてのデータ点を使用 · 正規データに最も効率的 · 外れ値に非常に敏感 · ブレークダウンポイント:0%

MAD

最も頑健な指標 · 中央値を使用(平均ではない) · あらゆる外れ値に免疫 · ブレークダウンポイント:50%

IQR

理解しやすい · 箱ひげ図で使用 · 極端な50%を無視 · ブレークダウンポイント:25%

頑健統計を使うべき場面

  • 探索的分析: 外れ値が存在するかわからない場合、頑健な指標から始める
  • データ品質に問題がある場合: エラーや測定上の問題を含む可能性があるデータ
  • 裾の重い分布: 極端な値が予想される場合(金融リターン、保険金請求額)
  • 小さな標本: 観測数が少ないため外れ値の影響が大きくなる場合
  • 外れ値検出: SDを使って外れ値を検出するのは循環論法。代わりにIQRやMADを使用

実装例

Python
import numpy as np
from scipy import stats

def mad(data):
    """Median Absolute Deviation"""
    median = np.median(data)
    return np.median(np.abs(data - median))

def scaled_mad(data):
    """MAD scaled to estimate SD (for normal data)"""
    return 1.4826 * mad(data)

def iqr(data):
    """Interquartile Range"""
    return np.percentile(data, 75) - np.percentile(data, 25)

# Compare on data with outlier
data = [10, 12, 11, 13, 12, 11, 100]
print(f"SD: {np.std(data, ddof=1):.2f}")
print(f"MAD: {mad(data):.2f}")
print(f"Scaled MAD: {scaled_mad(data):.2f}")
print(f"IQR: {iqr(data):.2f}")