IQR(Interquartile Range: 四分位範囲)は、データの散らばり具合を表す基本的な統計量です。標準偏差と並んで、データのばらつきを測るための重要な指標として、論文やデータ分析の場面で非常によく登場します。
本記事では、IQRの定義から外れ値検出への応用、箱ひげ図との関係、Pythonでの実装までを解説します。
本記事の内容
- 四分位数とIQRの定義
- IQRによる外れ値検出
- 箱ひげ図との関係
- Pythonでの実装と可視化
前提知識
この記事を読む前に、以下の概念を理解しておくと読みやすくなります。
- 中央値の定義
- 基本的な記述統計(平均、分散、標準偏差)
四分位数とは
IQRを理解するために、まず四分位数(Quartile)について確認しましょう。
データを小さい順に並べたとき、
- 第1四分位数(Q1): データの25%点(下位25%と上位75%の境界)
- 第2四分位数(Q2): データの50%点(中央値)
- 第3四分位数(Q3): データの75%点(下位75%と上位25%の境界)
例えば、データ $\{2, 4, 6, 8, 10, 12, 14, 16, 18, 20\}$ の場合:
$$ Q1 = 5, \quad Q2 = 11, \quad Q3 = 17 $$
四分位数は、データを4等分する3つの値です。
IQRの定義
IQR(四分位範囲)は、第3四分位数と第1四分位数の差として定義されます。
$$ \begin{equation} \text{IQR} = Q3 – Q1 \end{equation} $$
上の例では $\text{IQR} = 17 – 5 = 12$ です。
IQRは「データの中央50%が広がっている範囲」を表しています。
IQRの特徴
| 特徴 | 説明 |
|---|---|
| ロバスト性 | 外れ値の影響を受けにくい(標準偏差と異なる) |
| 直感的 | 「データの真ん中半分の広がり」という明快な意味 |
| 分布非依存 | 正規分布を仮定しない |
| 順序統計量 | データの値ではなく順位に基づく |
IQRと標準偏差の比較
データの散らばりを測る指標として、IQRと標準偏差 $\sigma$ はよく比較されます。
データが正規分布 $\mathcal{N}(\mu, \sigma^2)$ に従う場合、四分位数は次のようになります。
$$ \begin{align} Q1 &= \mu – 0.6745\sigma \\ Q3 &= \mu + 0.6745\sigma \end{align} $$
したがって、
$$ \begin{equation} \text{IQR} = Q3 – Q1 = 2 \times 0.6745\sigma = 1.349\sigma \end{equation} $$
正規分布のもとでは $\text{IQR} \approx 1.35\sigma$ という関係があります。
しかし、外れ値が存在する場合、標準偏差は大きく影響を受けるのに対し、IQRはほとんど影響を受けません。これがIQRの「ロバスト性」です。
IQRによる外れ値検出
IQRは外れ値の検出に広く使われています。Tukey(テューキー)の方法では、次の範囲外のデータ点を外れ値とみなします。
$$ \begin{equation} \text{外れ値}: x < Q1 - 1.5 \times \text{IQR} \quad \text{または} \quad x > Q3 + 1.5 \times \text{IQR} \end{equation} $$
さらに極端な値($1.5$ の代わりに $3.0$ を使う)は極端な外れ値とみなされます。
なぜ1.5倍なのか?
データが正規分布に従う場合、$Q1 – 1.5 \times \text{IQR}$ と $Q3 + 1.5 \times \text{IQR}$ はそれぞれ
$$ \begin{align} Q1 – 1.5 \times \text{IQR} &= \mu – 0.6745\sigma – 1.5 \times 1.349\sigma = \mu – 2.698\sigma \\ Q3 + 1.5 \times \text{IQR} &= \mu + 0.6745\sigma + 1.5 \times 1.349\sigma = \mu + 2.698\sigma \end{align} $$
に対応します。正規分布で $\mu \pm 2.698\sigma$ の外側に入る確率は約0.7%(両側合計)です。つまり、正規分布を仮定した場合、約99.3%のデータがこの範囲内に収まります。
箱ひげ図(Box Plot)との関係
箱ひげ図は、IQRを視覚的に表現したグラフです。
箱ひげ図の各要素:
- 箱の下端: Q1
- 箱の中の線: Q2(中央値)
- 箱の上端: Q3
- 箱の高さ: IQR
- 下のひげ: $Q1 – 1.5 \times \text{IQR}$ 以上の最小値
- 上のひげ: $Q3 + 1.5 \times \text{IQR}$ 以下の最大値
- 点: ひげの外側の値(外れ値)
Pythonでの実装
IQRの計算、外れ値検出、箱ひげ図の描画をPythonで実装します。
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
# データ生成(正規分布 + 外れ値)
n = 200
data_normal = np.random.normal(loc=50, scale=10, size=n)
# 外れ値を追加
outliers = np.array([5, 10, 95, 100, 110])
data = np.concatenate([data_normal, outliers])
# IQRの計算
Q1 = np.percentile(data, 25)
Q2 = np.percentile(data, 50)
Q3 = np.percentile(data, 75)
IQR = Q3 - Q1
# 外れ値の検出
lower_fence = Q1 - 1.5 * IQR
upper_fence = Q3 + 1.5 * IQR
outlier_mask = (data < lower_fence) | (data > upper_fence)
n_outliers = np.sum(outlier_mask)
print(f"Q1 = {Q1:.2f}")
print(f"Q2 (中央値) = {Q2:.2f}")
print(f"Q3 = {Q3:.2f}")
print(f"IQR = {IQR:.2f}")
print(f"下限フェンス = {lower_fence:.2f}")
print(f"上限フェンス = {upper_fence:.2f}")
print(f"外れ値の数 = {n_outliers}")
print(f"外れ値: {data[outlier_mask]}")
# IQRと標準偏差の比較(ロバスト性のデモ)
# 汚染率を変えて比較
contamination_rates = np.linspace(0, 0.2, 20)
iqr_values = []
std_values = []
for rate in contamination_rates:
n_contam = int(n * rate)
clean_data = np.random.normal(50, 10, n)
if n_contam > 0:
contam_data = np.random.normal(150, 5, n_contam) # 外れ値
mixed_data = np.concatenate([clean_data, contam_data])
else:
mixed_data = clean_data
iqr_values.append(np.percentile(mixed_data, 75) - np.percentile(mixed_data, 25))
std_values.append(np.std(mixed_data))
# 可視化
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 左上: ヒストグラムと四分位数
axes[0, 0].hist(data, bins=30, alpha=0.7, color='steelblue', edgecolor='black')
axes[0, 0].axvline(Q1, color='orange', linewidth=2, linestyle='--', label=f'Q1 = {Q1:.1f}')
axes[0, 0].axvline(Q2, color='red', linewidth=2, linestyle='-', label=f'Q2 = {Q2:.1f}')
axes[0, 0].axvline(Q3, color='green', linewidth=2, linestyle='--', label=f'Q3 = {Q3:.1f}')
axes[0, 0].axvline(lower_fence, color='purple', linewidth=1.5, linestyle=':',
label=f'Lower fence = {lower_fence:.1f}')
axes[0, 0].axvline(upper_fence, color='purple', linewidth=1.5, linestyle=':',
label=f'Upper fence = {upper_fence:.1f}')
axes[0, 0].set_xlabel('Value')
axes[0, 0].set_ylabel('Count')
axes[0, 0].set_title('Histogram with Quartiles and Fences')
axes[0, 0].legend(fontsize=8)
# 右上: 箱ひげ図
bp = axes[0, 1].boxplot(data, vert=True, patch_artist=True,
boxprops=dict(facecolor='lightblue', color='navy'),
medianprops=dict(color='red', linewidth=2),
flierprops=dict(marker='o', markerfacecolor='red', markersize=8))
axes[0, 1].set_ylabel('Value')
axes[0, 1].set_title('Box Plot')
# IQRの範囲を注釈
axes[0, 1].annotate('', xy=(1.15, Q3), xytext=(1.15, Q1),
arrowprops=dict(arrowstyle='<->', color='orange', lw=2))
axes[0, 1].text(1.2, (Q1+Q3)/2, f'IQR = {IQR:.1f}', fontsize=11, color='orange',
va='center')
# 左下: 外れ値の検出結果
normal_mask = ~outlier_mask
axes[1, 0].scatter(np.arange(len(data))[normal_mask], data[normal_mask],
c='steelblue', s=15, alpha=0.5, label='Normal')
axes[1, 0].scatter(np.arange(len(data))[outlier_mask], data[outlier_mask],
c='red', s=50, marker='x', linewidths=2, label='Outlier')
axes[1, 0].axhline(upper_fence, color='purple', linestyle='--', alpha=0.5,
label=f'Upper fence ({upper_fence:.1f})')
axes[1, 0].axhline(lower_fence, color='purple', linestyle='--', alpha=0.5,
label=f'Lower fence ({lower_fence:.1f})')
axes[1, 0].set_xlabel('Index')
axes[1, 0].set_ylabel('Value')
axes[1, 0].set_title('Outlier Detection using IQR')
axes[1, 0].legend(fontsize=9)
# 右下: IQRとstdのロバスト性比較
axes[1, 1].plot(contamination_rates * 100, iqr_values / iqr_values[0], 'b-o',
markersize=4, label='IQR (normalized)')
axes[1, 1].plot(contamination_rates * 100, std_values / std_values[0], 'r-o',
markersize=4, label='Std (normalized)')
axes[1, 1].set_xlabel('Contamination Rate [%]')
axes[1, 1].set_ylabel('Normalized Value')
axes[1, 1].set_title('Robustness: IQR vs Standard Deviation')
axes[1, 1].legend()
axes[1, 1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
左上のグラフでは、ヒストグラム上にQ1、Q2(中央値)、Q3とフェンス(外れ値の判定閾値)を示しています。右上の箱ひげ図では、IQRが箱の高さとして視覚的に表現されています。左下では、IQR法による外れ値検出の結果を示し、右下ではIQRと標準偏差のロバスト性を比較しています。外れ値の混入率が増えても、IQRはほとんど変化しないのに対し、標準偏差は大きく膨らんでいることがわかります。
まとめ
本記事では、IQR(四分位範囲)について解説しました。
- IQRは $Q3 – Q1$ で定義される、データの中央50%の広がりを表す統計量である
- 外れ値に対してロバスト(頑健)で、標準偏差よりも汚染データに強い
- Tukeyの方法により、$Q1 – 1.5 \times \text{IQR}$ 未満または $Q3 + 1.5 \times \text{IQR}$ 超のデータを外れ値として検出できる
- 箱ひげ図はIQRを視覚的に表現するグラフであり、データの分布を直感的に把握できる
次のステップとして、以下の記事も参考にしてください。