論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
外れ値
Outlier
他のデータから著しく離れた値。相関係数や平均を大きく歪めることがあり、必ず散布図で確認すべき。
データ前処理異常値outliers

🔖 キーワード索引 — この用語を多角的に理解する

外れ値(outlier)を理解するための関連キーワードを、難易度・カテゴリで整理しました。学習順序の参考にしてください。

🟢 基礎キーワード(まず押さえる)

🟡 中級キーワード(応用で必要)

🔴 上級キーワード(研究・実務の先端)

💡 30秒で分かる結論

🍰 まずはやさしく

外れ値は、仲間から大きく離れた値のことです。

正しい分析結果を出すために使います。

テストで一人だけ点数が極端に高い人がいる例です。

外れ値の種類と、その扱い方を学びます。

📖 もっと詳しく

外れ値(outlier)は、 他のデータから著しく離れた値です。 47都道府県データなら、 東京(人口密度が突出)沖縄(独自の人口構成) がしばしば外れ値として浮上します。

外れ値の正体は3パターン:(i) 入力ミス・測定エラー(除外すべき)、 (ii) システム的なエラー(要修正)、 (iii) 本当に特異な実体(東京、 沖縄 etc.、 重要な情報源)。 (iii) を機械的に除外するのは分析の改ざんに近い禁じ手です。

影響:外れ値は平均・分散・相関係数・回帰係数を強く歪めます。 一方で中央値・順位相関は外れ値に影響されにくい(ロバスト統計量)。

検出と対処:(i) 散布図と箱ひげ図で必ず可視化、 (ii) Tukey の基準(Q1−1.5·IQR より下、 Q3+1.5·IQR より上)、 (iii) Spearman 順位相関で頑健性を確認、 (iv) 外れ値含む結果と除外した結果の両方を提示する。

📍 あなたが今見ているもの

🍰 まずはやさしく

外れ値は、データの集まりから浮いた値です。

分析のミスを防ぐために確認します。

スマホの利用時間が極端に長い人がいる例です。

定義から具体的な使い方までを詳しく読みます。

論文中に 「外れ値」として登場する用語。

外れ値 とは:他のデータから著しく離れた値。相関係数や平均を大きく歪めることがあり、必ず散布図で確認すべき。

本ページでは「outlier」を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 複数年 × 100 超列) の実データを使った再現可能な学習を目指す。

「outlier」は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。

🎨 直感で掴む — 外れ値とは「群れから離れた星」

🍰 まずはやさしく

外れ値は、群れから離れた星のようなものです。

データの本当の姿を掴むために使います。

部活の練習時間だけ一人で違う人がいる例です。

図を使って、外れ値の見つけ方を考えます。

SSDSE-B-2026 の 47 都道府県人口を縦軸にプロットすると、 46 県は約 54 万〜920 万人の帯にまとまり、 東京都だけが 1,409 万人と「群れから離れた星」のように夜空に浮きます。 これが外れ値の典型像。「群れの位置(中央値)」と「群れの広がり(IQR)」を物差しにし、 そこから 1.5 倍以上離れている星を外れ値とみなす、 というのが Tukey の定義です。 ヒストグラムでは群れが山に、 外れ値が右端の小さな突起になります。

大事なのは「離れている=排除」ではない、 という思考。 東京の人口は誤入力ではなく真実です。 集計に含めると平均人口が約 265 万人と膨らみますが、 中央値 155 万人なら東京がいても揺らぎません。 つまり「平均派(外れ値の影響を受ける)」と「中央値派(影響を受けない)」を使い分けるのが、 外れ値時代の分析家の作法です。

🎨 概念図で押さえる

外れ値の定義検出方法を、 3 点の SVG で押さえる。

図1 箱ひげ図による外れ値判定(1.5×IQR ルール)

箱ひげ図と外れ値

箱の外、 ひげの外側に出た点が外れ値候補(Q1−1.5IQR より下、 Q3+1.5IQR より上)。

図2 Z-score 法

Z-scoreによる外れ値

標準正規分布で |Z|>3(または 2)の点を外れ値とみなす。 ただし元データが正規でないと過剰検出。

図3 SSDSE-B 都道府県データの典型的外れ値

都道府県データの外れ値

東京都が常に右上の極端値となる典型例。 平均・相関が東京 1 点に支配される。

📝 理解度チェック

  1. 箱ひげ図で「外れ値」となる閾値は? (答:Q1−1.5×IQR 未満、 Q3+1.5×IQR 超)
  2. Z-score 法で外れ値とする一般的な基準は? (答:|Z|>3 が多い、 厳しめなら |Z|>2)
  3. 外れ値は常に削除すべきか? (答:No。 入力誤りなら修正、 真の外れ値ならロバスト統計や層別が選択肢)
  4. 外れ値に強い中心傾向は平均中央値か? (答:中央値)
  5. SSDSE-B-2026 で典型的に外れ値となる都道府県は? (答:東京都が多くの指標で極端値)

🎮 触って理解する

下の数直線には説明用のサンプルデータ(11 点)が並んでいます(実測値ではなく操作体験のための架空値です)。 どれか 1 点をドラッグ(スマホは指でなぞる)して極端な位置へ動かすと、 平均・中央値・標準偏差・四分位範囲(IQR)がリアルタイムで再計算され、 外れ値と判定された点が色を変えます。 「平均は外れ値に引きずられるのに、 中央値と IQR はほとんど動かない」という頑健性(robustness)の違いを、 自分の手で確かめてください。

z 境界: 凡例: 通常  外れ値(IQR)  |z| 超過
平均 x̄
中央値 (median)
標準偏差 s (n−1)
IQR = Q3 − Q1
Q1 / Q3
/
IQR フェンス(下 / 上)
/
z 境界(下 / 上)
/
外れ値と判定された点

🧭 3 つの視点で深掘り

直感:外れ値は「群れから離れた 1 匹」。 中心を平均で測ると離れた 1 匹に手を引かれて中心がズレるが、 中央値で測れば多数派の位置が保たれます。 散らばりも同じで、 標準偏差は外れ値で膨張する一方、 IQR(真ん中 50% の幅)はほとんど動きません。 これが「頑健(robust)」という言葉の中身です。 ウィジェットで 1 点を右端へ動かすと、 赤い平均線が点を追いかけ、 緑の中央値線と青い IQR の箱がほぼ静止するのが見えます。

よくある落とし穴外れ値 ≠ 誤りです。 SSDSE-B-2026 の東京都のように、 外れ値がむしろ最も重要な情報であることは珍しくありません。 「外れ値だから」と機械的に除去するのは、 分布を都合よく整形する改ざんに近い危険な操作です。 除去の前に必ず (1) 入力誤り・測定エラーか、 (2) 本当に特異な実体か を切り分け、 除去した場合は件数・理由・除去前後の結果を必ず併記します。 また z スコア法は、 極端な 1 点自身が平均と標準偏差を膨らませて境界を広げるため、 その点を取りこぼす(マスキング)ことがあります。 ±2σ / ±3σ を切り替えて、 IQR 法は捕まえるのに z 法が見逃す様子を確認してみてください。

発展(頑健統計):外れ値の影響を受けにくい統計量・手法を頑健統計と呼びます。 中央値・IQR・MAD(中央絶対偏差)・修正 z スコア・Huber 回帰・RANSAC などが代表例です。 「壊れにくさ」はブレークダウンポイントで測られ、 中央値は 50%(半分が外れ値でも耐える)、 平均は 0%(1 点で破綻)です。 上のウィジェットで平均線が動くのに中央値線が動じない様子は、 まさにこの差を可視化したものです。

関連ページ: 中央値標準偏差四分位範囲(IQR)箱ひげ図MAD頑健統計外れ値処理

📐 定義・数式 — 3 つの外れ値基準

🍰 まずはやさしく

外れ値は、数式で判定できる特別な値です。

客観的に外れ値を決めるために使います。

買い物の金額が平均よりずっと高い例です。

外れ値を判定するための3つの基準を読みます。

  1. z-score 基準(正規分布前提):$z_i = (x_i - \bar{x}) / s$ で $|z_i| > 3$ を外れ値とみなす。
  2. Tukey IQR 基準(分布フリー):$x_i < Q_1 - 1.5 \cdot \text{IQR}$ または $x_i > Q_3 + 1.5 \cdot \text{IQR}$。 ただし IQR $= Q_3 - Q_1$。
  3. 修正 z-score (MAD 基準・ロバスト):$z^*_i = 0.6745 \cdot (x_i - \tilde{x}) / \text{MAD}$、 $\text{MAD} = \text{median}(|x_i - \tilde{x}|)$。 $|z^*_i| > 3.5$ を外れ値。
  4. 多変量:Mahalanobis 距離:$d^2_i = (\mathbf{x}_i - \boldsymbol{\mu})^\top \Sigma^{-1} (\mathbf{x}_i - \boldsymbol{\mu})$。 $\chi^2_{p, 0.975}$ 超で外れ値。

SSDSE-B-2026 の人口データは右に強く歪むため、 1 と 2 は東京を確実に拾うが地方の異常検出には甘い。 3 は中央値・MAD ベースで歪みに頑健、 4 は複数指標を組み合わせる際の標準。

🔬 数式を言葉で読み解く — 記号 → 意味

記号意味SSDSE-B-2026 での具体例
$\bar{x}, s$標本平均と標本標準偏差A1101 の 47 県平均 ≈ 265 万人、 SD ≈ 280 万人
$\tilde{x}$中央値(外れ値に頑健)A1101 の中央値 ≈ 155 万人(鹿児島県あたり)
$Q_1, Q_3, \text{IQR}$第 1 ・第 3 四分位とその差A1101 で IQR ≈ 160 万人。 1.5×IQR ≈ 240 万人
MAD中央絶対偏差(ロバスト SD 代替)A1101 の MAD ≈ 62 万人。 ÷0.6745 で SD 相当に正規化
$\Sigma$共分散行列(多変量の広がり)食料費・教育費・住居費の (3,3) 行列

読み方:「中央 ($\tilde{x}, Q$) からどれだけ離れているか」を「広がり (IQR, MAD)」で割って、 規格化された距離で判断する、 が外れ値検出の本質です。

📖 包括的解説 — この概念を完全マスター

📍 学習の3ステップ

  1. 定義を理解する:この概念は何か? 数式や条件を確認
  2. 具体例を見る:実データ(SSDSE 等)で計算してみる
  3. 応用する:自分のデータに適用、 結果を解釈

🔧 Python実装パターン

🎯 目的:SSDSE-B-2026 を読み込み、 describe() で外れ値判定の基本指標(平均・SD・四分位)を一望し、 さらに A1101(総人口)の箱ひげ図を眺めて視覚的に異常な県(東京都)を見つける。
📥 入力data/raw/SSDSE-B-2026.csv (CP932 エンコード、 2 行目に日本語見出し行があるので skiprows=[1])。 df['SSDSE-B-2026']==2023 で年度を 1 つに絞り 47 都道府県 × 1 年に整える。 注目列:A1101(総人口)。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 基本パターン
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns

# データ読み込み(SSDSE-B は cp932。2 行目に日本語見出しがあるので skiprows)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]      # 年度を 2023 年に絞る(47 行)

# 基本統計量(A1101 = 総人口)
print(df['A1101'].describe())

# 可視化:総人口の箱ひげ図で東京都の突出を確認
df.boxplot(column='A1101')
plt.show()
📤 出力(A1101=総人口、単位:人。値は概算) df['A1101'].describe() count 47.0 mean 2645809.0 std 2797551.0 min 537000.0 ← 鳥取県 25% 1034000.0 50% 1549000.0 ← 中央値(鹿児島県あたり) 75% 2636500.0 max 14086000.0 ← 東京都(突出した外れ値) Name: A1101, dtype: float64
💬 解釈:max(東京都・約 1,409 万人)が 75% 点+1.5×IQR を大きく超える。 総人口は右に強く歪む分布で、 東京都・神奈川県・大阪府など都市圏が上側の外れ値候補として並ぶ。 箱ひげ図では東京都のみがひげの外へ大きく飛び出し、 平均(約 265 万人)が中央値(約 155 万人)より高い「右裾の長い分布」であることが一目で分かる。

📚 統計概念マップでの位置

このページの上にある3つの概念マップ(関係マップ、 包含マップ、 ツリーマップ)でこの概念の位置づけが視覚的に分かります。 関連手法を辿って学習を進めましょう。

🎯 SSDSE-B-2026 で挑戦

統計データ活用コンペティションのSSDSE-B-2026データは、 47都道府県の社会経済データ。 この概念を使って以下のような分析ができます:

💡 よく使うコマンド集

機能 Python (pandas) Python (scipy)
要約統計df.describe()stats.describe()
平均df.mean()np.mean()
標準偏差df.std()np.std()
相関df.corr()stats.pearsonr()
t検定stats.ttest_ind()
回帰stats.linregress()
分布フィッティングstats.norm.fit()

🚧 一般的な落とし穴と対策

📊 結果報告の標準フォーマット

🌐 関連分野での応用

🎓 さらに学ぶための文献

🔗 統計用語ネットワーク

この概念は、 他の多くの統計概念と密接に関連しています。 ジャストインタイム型学習では、 必要に応じて関連用語へジャンプしながら全体像を構築します。

主要な関連概念のグループ

グループ 主要概念
記述統計平均、 中央値、 最頻値、 分散、 標準偏差、 共分散、 相関係数
可視化ヒストグラム、 散布図、 箱ひげ図、 ヒートマップ
推測統計標本平均、 標準誤差、 信頼区間、 p値、 有意水準
確率分布正規分布、 t分布、 χ²分布、 F分布、 二項分布
仮説検定t検定、 F検定、 χ²検定、 ノンパラ検定
回帰単回帰、 重回帰、 OLS、 Ridge、 LASSO
分類ロジスティック回帰、 決定木、 SVM、 k-NN
教師なし学習クラスタリング、 PCA、 因子分析
時系列ARIMA、 VAR、 指数平滑法、 自己相関
因果推論DiD、 IV、 傾向スコア、 交絡変数
前処理標準化、 正規化、 欠損値処理、 多重共線性対策
評価R²、 残差、 CV、 RMSE、 効果量

学習順序の推奨

  1. 記述統計(平均、 分散、 標準偏差)
  2. 可視化(ヒストグラム、 散布図)
  3. 確率分布(正規分布)
  4. 推測統計(標準誤差、 信頼区間、 p値)
  5. 仮説検定(t検定、 χ²検定)
  6. 相関と回帰(単回帰、 重回帰)
  7. 多変量解析(PCA、 クラスタリング)
  8. 機械学習(決定木、 RF、 NN)
  9. 時系列・因果推論(応用)

📝 実践練習 — SSDSE-B-2026 で挑戦

初級課題

  1. 東北6県の家計食料費の基本統計量を計算
  2. 食料費のヒストグラムを描く
  3. 食料費と教育費の散布図を描く
  4. 都道府県を「東日本/西日本」に分け、 平均を比較

中級課題

  1. 家計支出 5項目で相関行列を作成、 ヒートマップ可視化
  2. 食料費 → 教育費の単回帰を実行、 残差分析
  3. 家計5項目で PCA を実施、 バイプロット表示
  4. k-means (k=3) で都道府県をクラスタリング、 解釈

上級課題

  1. 地域別の家計パターンに有意差があるか ANOVA で検定
  2. 重回帰で教育費を予測、 多重共線性を VIF で確認
  3. Ridge/LASSO で正則化、 CV で α を最適化
  4. 階層クラスタリングと Ward 法で都道府県を分類、 デンドログラム作成

🧮 SSDSE-B-2026 実値計算例 — 47 都道府県データで外れ値を炙り出す

ここでは合成データではなく、SSDSE-B-2026 の実データ「総人口(A1101)」と、そこから導かれる「人口密度」を題材に、外れ値を見つける手順を具体的な数値で示します。

① 人口(2020 年国勢調査・47 都道府県)の外れ値判定

47 都道府県の人口(単位:万人、 概算値)をソートすると:

Tukey の基準で外れ値を計算:

# Q1 ≈ 103(25%点:山形・宮崎のあたり)
# Q3 ≈ 264(75%点:京都・広島のあたり)
# IQR = Q3 - Q1 ≈ 160
# 上限 = Q3 + 1.5 × IQR ≈ 264 + 240 = 504
# 下限 = Q1 - 1.5 × IQR ≈ 103 - 240 = -137 → 0 以下なので意味なし

外れ値の判定:人口 > 504 万人の都道府県
 → 東京(1409)、 神奈川(923)、 大阪(876)、 愛知(748)、 埼玉(733)、 千葉(626)、 兵庫(537)、 福岡(510)、 北海道(509)
 → 9 都道府県が「外れ値」

解釈:都市圏 9 都道府県が統計的に「外れ値」と判定されますが、これらは除外すべきではない真の特異点です。この場合、対数変換 log₁₀(人口) を施せば多くの都道府県が中央に収まり、外れ値は東京のみ(log₁₀ 1409 ≈ 7.15、 全体平均 ≈ 6.3)に縮減されます。

② Z スコアによる「人口密度」の外れ値(東京の極端さ)

|Z|>3 の基準では、 東京・大阪が外れ値と判定されます。ただし、平均と標準偏差が東京自体に強く引きずられているため、 MAD ベースの修正 Z スコアで再計算すると東京の特異性がさらに鮮明になります。

③ 修正 Z スコア(MAD ベース)の例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# A1101(総人口) に対する MAD ベースの修正Zスコア
import numpy as np

x = df['A1101'].to_numpy()
med = np.median(x)
mad = np.median(np.abs(x - med))          # 中央絶対偏差
mz = 0.6745 * (x - med) / mad             # |修正Z| > 3.5 を外れ値とみなす

flagged = df.loc[np.abs(mz) > 3.5, 'Prefecture']
print(flagged.tolist())                    # 東京都が突出して検出される

🧮 SSDSE-B-2026 拡張ハンズオン — 47 都道府県を 3 つのルールで外れ値検出

ここでは data/raw/SSDSE-B-2026.csv を実際に読み込み、 A1101(総人口)1 列に対して外れ値検出を 3 方式(IQR / Z スコア / MAD)で比較します。 同じデータでも手法によって外れ値リストがどう変わるかを 47 都道府県の固有名で確認することで、 「どの基準が業務に合うか」を直感で掴めます。

🎯 学習目的

3 つのルール(IQR・Z スコア・MAD)が同じ列(総人口)に対して違う外れ値リストを返すことを実データで体感する。

📥 入力

data/raw/SSDSE-B-2026.csvPrefecture 列と A1101(総人口)列。 encoding='cp932'skiprows=[1] で読み込み、 df['SSDSE-B-2026']==2023 で年度を 1 つに絞る。

📤 出力

3 ルール別の外れ値フラグ表(True/False)と、 いずれかの基準で外れ値と挙がった都道府県の一覧。

💬 解説

東京都は総人口が突出しているため、 IQR・Z スコア・MAD のすべてで外れ値になる。 神奈川県・大阪府は平均・標準偏差ベース(Z・IQR)では挙がるが、 中央値・MAD ベースでは基準や年により境界線上になることがある。 こうした県固有の挙動を、 ルールの違いとして読み取れるようになるのが目標です。

🐍 比較スクリプト

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]        # 年度を 2023 年に固定

def by_iqr(s):
    q1, q3 = s.quantile([.25, .75])
    iqr = q3 - q1
    return (s < q1 - 1.5*iqr) | (s > q3 + 1.5*iqr)

def by_z(s, k=2.5):
    return ((s - s.mean()) / s.std()).abs() > k

def by_mad(s, k=3.5):
    med = s.median()
    mad = (s - med).abs().median()
    if mad == 0:
        return pd.Series(False, index=s.index)
    return (0.6745 * (s - med) / mad).abs() > k

s = df['A1101']                            # A1101 = 総人口
# by_* が返す Series の索引は df の行番号。そこへ index=都道府県名 を渡すと
# 索引が一致せず全部 NaN になり、外れ値が 1 件も出なくなる。値だけを渡す。
flags = pd.DataFrame({
    'IQR':    by_iqr(s).values,
    'Zscore': by_z(s).values,
    'MAD':    by_mad(s).values,
}, index=df['Prefecture'].values)
print(flags[flags.any(axis=1)])

読み解きの観点

❓ よくある質問 — 外れ値の意思決定 12 問

Q1. 外れ値を除外するべきか、 残すべきか

原則は「業務目的外れ値の発生メカニズムの二軸で決める」。 計測誤差由来なら除外、 真に稀な現象なら保持。 SSDSE-B-2026 で東京都を除外するなら、 「全国を代表する分析である」と業務目的が明示できるときに限る。

Q2. 同じデータで IQR・Z スコア・MAD のどれを使うべきか

標本サイズが小さく分布の歪みが大きいならMAD。 標本サイズが十分(n > 100 目安)で対称な分布なら Z スコアで良い。 IQR は読み手の直感に近く可視化との相性が良いため、 説明用にしばしば使われる。

Q3. 多変量の外れ値検出はどう始めるか

Mahalanobis 距離 → Isolation Forest → LOF の順で試すのが効率的。 まず Mahalanobis で楕円外を抽出し、 非線形構造があれば Isolation Forest / LOF で再検査する。

Q4. 外れ値処理の前後でモデル評価指標はどう変わるか

外れ値を除外すると訓練 R^2 は通常上がるが、 汎化性能は下がる場合がある。 ホールドアウト test set に外れ値が含まれるなら、 訓練側だけ外しても本番では困るので「Winsorize」「ロバスト損失」を併用する。

Q5. ログ変換は外れ値対策になるか

右に裾の長い分布なら効果的。 ただし負値・ゼロを含む場合は log1p や Box-Cox を使う。 SSDSE-B-2026 の「観光客数」「事業所数」のような幅広い指標は対数化が有効。

Q6. 機械学習モデルは自動で外れ値を扱ってくれるか

木系(Random Forest・XGBoost)は分割で吸収するため比較的頑健。 一方、 距離ベース(k-NN・SVM)や勾配ベース(線形・ニューラル)は外れ値の影響を大きく受ける。

Q7. 「3σ ルール」は実用的か

厳密には正規分布の仮定が前提。 SSDSE-B-2026 のように極端な歪みを持つ社会経済指標には不向きで、 IQR か MAD を使うべき。 ただし「ざっくり外れているか」のスクリーニングには手早い。

Q8. レポートには外れ値処理をどう書けばよいか

「使用した基準」「除外した観測の数と県名」「除外/保持で結論が変わるか感度分析した結果」の 3 点を最低限明示する。 これを書かない論文は再現できない。

Q9. 外れ値が「重要な発見」である場合の扱いは

除外せず、 むしろ主分析の主役に据える。 「東京都だけが特殊である」こと自体が政策的に重要なら、 全国平均との比較ではなく東京都を分離した分析を立てる。

Q10. 標本サイズが小さい場合の外れ値検出

n < 30 では Grubbs 検定や Dixon 検定など個別検定に頼り、 多重比較補正を入れる。 経験的ルール(IQR や 3σ)は標本数が少ないと信頼性が落ちる。

Q11. 外れ値検出を自動化するパイプラインはどう作るか

scikit-learn の PipelineIsolationForestEllipticEnvelope を組み込み、 contamination パラメータを CV で選ぶ。 さらに「業務側のホワイトリスト」を併用して、 制度的に特殊な観測を自動除外しない仕組みを併設する。

Q12. 外れ値処理は本当に必要か

常に必要というわけではない。 ロバスト回帰やランクベースの手法を使えば前処理不要。 「外れ値処理 + 通常モデル」と「外れ値処理なし + ロバストモデル」のどちらかを選ぶ、 と整理すると判断が早い。

🚀 発展研究の方向性 — 外れ値の最前線 6 題

🧮 数式に値を入れて手で計算する: 外れ値検出 (3σ ルール)

合成データで平均 ± 3σ の範囲外を外れ値として検出する。

Step 1: データ

x = [50, 52, 48, 53, 49, 51, 100] 平均 ≈ 57.6, σ ≈ 18.4 3σ 範囲: [2.4, 112.8]

Step 2: 外れ値判定

x=100: 100 > 平均+1.5σ だが 3σ 範囲内 小サンプルで σ が大きく算出される問題 IQR 法の方が頑健

Step 3: IQR 法

Q1=49.5, Q3=52.5, IQR=3 上限 = 52.5 + 1.5×3 = 57 100 > 57 → 外れ値 ✓

🐍 Python で再現

1
2
3
4
5
6
7
8
import numpy as np
x = np.array([50, 52, 48, 53, 49, 51, 100])
q1, q3 = np.percentile(x, [25, 75])
iqr = q3 - q1
upper = q3 + 1.5*iqr
out = x[x > upper]
print(f"Q1, Q3, IQR: {q1}, {q3}, {iqr}")
print(f"外れ値: {out}")

📤 実行結果

Q1, Q3, IQR: 49.5, 52.5, 3.0 外れ値: [100]

💬 手計算 (Step 3) 100 と Python 出力が完全一致。

🐍 Python 実装のバリエーション — scipy / scikit-learn / statsmodels

外れ値検出には複数のライブラリが利用できます。 用途に応じて使い分けましょう。

① scipy.stats による Grubbs 検定・Z スコア

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) 北海道 5,092,000 東京都 14,086,000 沖縄県 1,468,000 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
x = df['A1101'].dropna()                   # A1101 = 総人口

# Z スコア(平均・標準偏差ベース)
z = stats.zscore(x)
outliers_z = df.loc[abs(z) > 3, 'Prefecture']
print('Z スコア外れ値:', outliers_z.tolist())

# Grubbs 検定(最大外れ値を 1 つ検定:scipy に直接実装がないので手計算)
g = (x.max() - x.mean()) / x.std()
n = len(x)
t_crit = stats.t.ppf(1 - 0.05/(2*n), n-2)
g_crit = (n-1)/n**0.5 * (t_crit**2/(n-2+t_crit**2))**0.5
print(f'G統計量={g:.3f}, 棄却限界={g_crit:.3f}')
print('外れ値' if g > g_crit else '外れ値なし')

② scikit-learn の Isolation Forest(多変量・教師なし)

📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年) 年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) … 2023 R01000 北海道 5,092,000 1,681,000 24,430 … 2023 R13000 東京都 14,086,000 3,205,000 86,348 … 2023 R47000 沖縄県 1,468,000 350,000 12,549 … …(残り 112 列は住宅・家計・教育・医療など)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from sklearn.ensemble import IsolationForest
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]

# 数値列(年度コード列を除く)をまとめて多変量入力に
X = df.select_dtypes('number').drop(columns=['SSDSE-B-2026'])

# contamination は外れ値の想定割合
clf = IsolationForest(contamination=0.1, random_state=0)
clf.fit(X)
out = pd.DataFrame({'Prefecture': df['Prefecture'].values}, index=X.index)
out['outlier'] = clf.predict(X)            # -1 = 外れ値、1 = 正常
out['score']   = clf.decision_function(X)
print(out[out['outlier'] == -1].sort_values('score'))

③ scikit-learn の Local Outlier Factor(密度ベース)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from sklearn.neighbors import LocalOutlierFactor

lof = LocalOutlierFactor(n_neighbors=5, contamination=0.1)
labels = lof.fit_predict(X)
neg_score = -lof.negative_outlier_factor_  # 大きいほど外れ値らしい

result = X.copy()
result['LOF_label'] = labels
result['LOF_score'] = neg_score
print(result.sort_values('LOF_score', ascending=False).head(10))

④ statsmodels の影響量診断(回帰モデル用)

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) 北海道 5,092,000 東京都 14,086,000 沖縄県 1,468,000 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import pandas as pd
import statsmodels.api as sm

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
num = df.select_dtypes('number').drop(columns=['SSDSE-B-2026']).dropna()

# A1101(総人口) を目的変数に、他の実在指標 2 列を説明変数として例示
y = num['A1101']
X = sm.add_constant(num.drop(columns=['A1101']).iloc[:, :2])

model = sm.OLS(y, X).fit()
influence = model.get_influence()

cook_d    = influence.cooks_distance[0]      # Cook の距離
std_resid = influence.resid_studentized_internal
leverage  = influence.hat_matrix_diag        # レバレッジ

diag = pd.DataFrame({
    'Prefecture': df.loc[num.index, 'Prefecture'].values,
    'cook_d': cook_d,
    'std_resid': std_resid,
    'leverage': leverage,
})
print(diag.sort_values('cook_d', ascending=False).head(5))

n = len(num)
print(f'Cook閾値 4/n = {4/n:.4f}')
print(f'Leverage閾値 2p/n = {2*3/n:.4f}')

⑤ MAD ベースの修正 Z スコア(手実装・ロバスト版)

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) 北海道 5,092,000 東京都 14,086,000 沖縄県 1,468,000 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import numpy as np
import pandas as pd

def modified_zscore(x):
    med = np.median(x)
    mad = np.median(np.abs(x - med))
    return 0.6745 * (x - med) / mad if mad > 0 else np.zeros_like(x)

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
x = df['A1101'].to_numpy()                 # A1101 = 総人口
mz = modified_zscore(x)

result = pd.DataFrame({'Prefecture': df['Prefecture'].values,
                       'A1101': x, '修正Z': mz})
print(result[np.abs(result['修正Z']) > 3.5]
      .sort_values('修正Z', key=np.abs, ascending=False))

⑥ One-Class SVM(半教師あり・滑らかな境界)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from sklearn.svm import OneClassSVM
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
Xs = scaler.fit_transform(X)

oc = OneClassSVM(gamma='auto', nu=0.1)
oc.fit(Xs)
labels = oc.predict(Xs)   # -1 = 外れ値
scores = oc.score_samples(Xs)

import pandas as pd
out = X.copy()
out['OCSVM_label'] = labels
out['OCSVM_score'] = scores
print(out[out['OCSVM_label'] == -1].sort_values('OCSVM_score'))

⚠️ 外れ値の落とし穴 — 実務で必ず引っかかるポイント 7 選

① 「外れ値 = 除去すべき」と短絡してしまう

初学者が最も陥りやすい誤解です。外れ値には (i) 入力ミス、 (ii) 測定エラー、 (iii) 真に特異な現象、 の 3 種があり、 (iii) を機械的に除外することは 分析の改ざんに近い禁じ手 です。47 都道府県データで東京を除外すれば、 確かに数値は綺麗になりますが、 それは「日本」を分析していると言えるでしょうか。外れ値の正体を診断し、 含めた結果と除外した結果の両方を提示するのが正しい姿勢です。

② Tukey の基準(±1.5·IQR)を絶対視する

「Q1 − 1.5·IQR より下、 Q3 + 1.5·IQR より上」は教科書的な目安ですが、 正規分布なら片側 0.35% 程度しか外れ値が出ない設定で、 裾の重い分布(人口、 所得、 売上)では大量の「正常な外れ値」が誤検出されます。47 都道府県の人口で 9 個も外れ値が出るのはそのためです。分布の形を確認し、 対数変換やロバスト指標と組み合わせることが必須です。

③ 平均と標準偏差で外れ値を検出する循環参照

「|Z| > 3 を外れ値とする」とき、 平均と標準偏差そのものが外れ値の影響を受けています。たとえば東京を含む人口密度の平均は 660、 除外すると 540、 さらに大阪を除くと 450 と次々動きます。この循環を断ち切るのが 中央値と MAD です。修正 Z スコア(0.6745·(xᵢ − median)/MAD)は外れ値自身に汚染されない、 ロバストな検出基準です。

④ 多変量の外れ値を 1 変数ずつチェックして見落とす

各変数を単独で見ると正常範囲なのに、 組み合わせて見ると異常な点が存在します。 たとえば「身長 170cm、 体重 50kg」はそれぞれ普通でも、 組み合わせとして痩せ過ぎ気味。 多変量の外れ値検出には Mahalanobis 距離Isolation ForestLocal Outlier Factor など、 多変量空間での密度・距離を考慮する手法を使う必要があります。

⑤ レバレッジと外れ値を混同する

回帰分析では「Y 方向の外れ値(残差が大きい)」と「X 方向の外れ値(説明変数が極端)」は別物です。 後者をレバレッジと呼びます。 レバレッジが高くても残差が小さければ影響は小さく、 逆にレバレッジと残差の両方が大きい点が Cook の距離 で警告される「影響点(influential point)」です。 残差プロットだけでは見つかりません。

⑥ 「外れ値を除外して再分析」を繰り返す p-hacking

p 値が有意にならないと外れ値を 1 個除外、 まだなら 2 個目を除外、 ……という逐次的な外れ値削除は p-hacking の典型です。事前に「Tukey の基準 + IQR 1.5 倍」など除外ルールを宣言し、 結果が変わっても固守する。 もしくは外れ値を含む結果と除外した結果の両方を併記する。 こうした透明性が再現性のある分析の要です。

⑦ 時系列データの外れ値を独立サンプルとして扱う

時系列ではトレンド・季節性・自己相関を考慮せずに「平均 ± 3SD」を当てはめると、 トレンドの上昇局面が全部外れ値判定されたり、 季節ピークが見逃されたりします。 時系列の外れ値検出には STL 分解後の残差ARIMA の予測区間からの逸脱変化点検出(CUSUM、 PELT) など、 時間構造を扱う手法が必要です。

🗺️ 統計手法選択フローチャート

Q1: 何を知りたい?

Q2: データの種類は?

Q3: サンプルサイズは?

Q4: 仮定は?

📏 効果量の参照表

p値だけでなく効果量も併記するのが現代統計の標準。 主要な指標と Cohen の解釈基準:

統計量 効果量
2群平均差Cohen's d0.20.50.8
相関r0.10.30.5
線形回帰0.020.130.26
ANOVAη² (eta²)0.010.060.14
χ²Cramér's V0.10.30.5
ロジスティックOdds Ratio1.52.54.0

🗺️ 概念マップ — 3つの視点で体系を理解する

外れ値 がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。

📍 体系階層のパス

🌐 統計・データサイエンス › 前処理 › データ品質 › 外れ値

① 🔗 関係マップ — 「他の手法とどう繋がっているか」

中心に 外れ値 を置き、 そこから 箱ひげ図・標準偏差・ヒストグラム・散布図・分散・平均 など 計 7 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語あとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。

凡例:現在の用語上位カテゴリ兄弟(並列)前提発展形応用先2階層先

② ⭕ 包含マップ — 「どのカテゴリに含まれているか」

大きな円が小さな円を包含する Circle Packing 図。 「外れ値」は緑色でハイライト

📍現在地:統計・データサイエンス

③ 🌳 ツリーマップ — 「面積で見るボリューム比較」

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「外れ値」は緑色でハイライト

🎯 3つのマップの使い分け

マップ 分かること こんな時に見る
🔗 関係マップ手法間の横の関係(前提→発展→応用)「次に何を学べばよい?」 学習順序の判断
⭕ 包含マップ分類体系の入れ子構造(上位⊃下位)「この手法はどんなジャンルに属する?」
🌳 ツリーマップ分野の規模比較(面積=ボリューム)「データサイエンス全体の俯瞰像」

💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは 外れ値隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンスデータ品質 → 外れ値 という入れ子の位置を示します。 「データ品質には他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。

🔗 隣接手法への橋渡し

「外れ値」は単独で完結せず、 前後の手法と組み合わさって価値が発揮される。 入力データの準備 (上流)・同目的の代替手法との比較 (並列)・結果の活用 (下流) という 3 軸で隣接領域を整理する。

この上流・並列・下流の対応を地図化することで、 「外れ値」を中核に据えた分析パイプライン (データ準備 → 手法選択 → 結果の検証と展開) の全体像が見えてくる。

🌳 外れ値処理の意思決定木 — 6 つの分岐

分岐 1: 計測誤差か真の値か

分岐 2: 業務目的が「全体傾向」か「特異な観測の発見」か

分岐 3: 単変量か多変量か

分岐 4: 分布の歪み

分岐 5: モデルへの感度

分岐 6: 報告

📖 外れ値関連用語ミニ辞典 — 12 語

Outlier
分布の他の値から大きく離れた観測。
Tukey IQR Rule
Q1-1.5*IQR と Q3+1.5*IQR の外側を外れ値とするルール。
Z スコア
(x - 平均) / 標準偏差。 |Z| > 3 で外れ値の経験則。
MAD (Median Absolute Deviation)
中央値からの絶対偏差の中央値。 ロバストな指標。
Modified Z-score
MAD ベースのロバスト Z スコア。 0.6745 * (x - median) / MAD。
Grubbs 検定
外れ値を 1 個ずつ検定する古典的手法。
Dixon 検定
小標本用の外れ値検定。 範囲比を使う。
Mahalanobis 距離
共分散構造を考慮した多変量距離。
Isolation Forest
木で「孤立しやすい点」を見つける異常検知。
LOF (Local Outlier Factor)
近傍密度の比で局所的外れ値を検出。
One-Class SVM
「正常データの境界」を SVM で学習する手法。
Winsorize
外れ値を一定の分位点で「すげ替える」処理。

✅ 外れ値処理の最終チェックリスト 12 項目

分析レポート提出前の自己点検として、 以下の 12 項目すべてに「Yes」と答えられるかを確認してください。 一つでも「No」があれば、 そのセクションに戻って補強する必要があります。

  1. 使用した外れ値検出ルール(IQR / Z スコア / MAD / Mahalanobis / Isolation Forest など)を明示したか。
  2. 除外した観測の県名・件数・除外理由を本文または付録に記載したか。
  3. 除外前後で結論が変わらないことを感度分析として示したか。
  4. 計測誤差由来か真の値か、 ドメイン知識で判定したか。
  5. 業務目的(全体傾向 vs 特異な発見)と外れ値処理が整合しているか。
  6. 単変量だけでなく多変量視点(Mahalanobis ・ Cook 距離)でも確認したか。
  7. 標本サイズが小さい場合、 Grubbs/Dixon 検定など個別検定を併用したか。
  8. ログ変換・ Box-Cox 変換で分布の歪みを緩和する選択肢を検討したか。
  9. ロバスト統計の代替手法(Huber 回帰 ・ MAD ベースのロバスト Z)を併用したか。
  10. SSDSE-B-2026 における東京都・沖縄県など制度的に特殊な県の扱いを文書化したか。
  11. 機械学習モデル使用時に「外れ値前処理 + 通常モデル」と「ロバストモデル」のどちらを選んだか言語化したか。
  12. 外れ値が「重要な発見」である可能性を排除しないチェックを行ったか。

📝 まとめノート — 外れ値

このページは「外れ値」を SSDSE-B-2026 (47 都道府県 × 多変量) を題材に体系的に学ぶための一気通貫の教材です。 単なる用語定義集ではなく、 「直感 → 数式 → 実装 → 落とし穴 → 関連手法」 という流れで一周することで、 業務での意思決定にそのまま使える知識に組み上げます。

本ページで取り上げた手法・記号・コード例は、 すべて実データの 47 都道府県を入力として動作する形にしてあります。 合成データに依存しないため、 SSDSE-B-2026 を data/raw/SSDSE-B-2026.csv として配置するだけでコード片を再現できます。

関連グループ教材へのリンクを使い、 「この用語が属する大きな分野」を俯瞰してから戻ってくると、 知識が一段抽象化された形で定着します。 用語ページは点、 グループ教材は線、 概念マップは面 — 三層を往復しながら学習を進めてください。

本ページの内容に不足を感じたら、 相関ページ(correlation.html)を参照基準として、 ご自身の解釈を加筆していくことを推奨します。 教材の完成形ではなく、 学習者自身の理解の出発点として位置付けてください。

最後に、 SSDSE-B-2026 の 47 都道府県データは「N=47 と少ない」という構造的制約があります。 統計検定の漸近近似が崩れる場面、 単一の県(東京都・沖縄県)が全体傾向を支配する場面、 標準誤差が過小評価される場面 — これらは本ページの随所で繰り返し注意喚起しました。 「実データの小ささを軽視しない」 という姿勢が、 実務でのデータサイエンティストの基本姿勢です。

📝 補足 — 2023 年実測で読む「手法ごとに外れ値リストが変わる」構造

本ページの各節は検出法を個別に説明してきました。 ここでは角度を変え、 SSDSE-B-2026 の 2023 年(47 都道府県)・総人口 A1101 という 1 本の同じ列に対して、 IQR・z スコア・MAD の 3 法を実際に走らせた結果を突き合わせます(encoding='cp932'skiprows=[1]df['SSDSE-B-2026']==2023 での実測値)。 「どの手法が正しいか」ではなく「同じデータでも手法で結論が変わる」ことを、 県の固有名と件数で確かめるのが狙いです。

直感 — 1 点が平均を「乗っ取る」を数字で見る

2023 年の総人口は 47 県で平均 約 265 万人、 中央値 約 155 万人。 平均が中央値より 110 万人も高いのは、 東京都(約 1,409 万人)を筆頭とする都市圏が右裾を引っ張るからです。 東京都1 点だけを除くと平均は約 240 万人へ下がります(約 9% の低下)。 47 分の 1 の観測が全体平均を 1 割動かす——これがブレークダウンポイント 0(平均は 1 点で破綻しうる)の実演で、 中央値がびくともしないのと好対照です。

実測比較表(総人口 A1101・2023 年・47 都道府県)

検出法基準外れ値と判定された県数顔ぶれ
Tukey IQRQ3+1.5·IQR ≈ 504 万人 超9 県北海道・埼玉・千葉・東京・神奈川・愛知・大阪・兵庫・福岡
修正 z(MAD 基準)|z*|>3.5(MAD ≈ 62.3 万人)9 県IQR と同一の 9 県(東京の z* ≈ 13.6 と突出)
z スコア|z|>31 県東京都のみ(z ≈ 4.09)
z スコア|z|>23 県東京・神奈川・大阪

同じ総人口 1 列でも、 IQR・MAD は 9 県を、 z スコア(|z|>3)はわずか 1 県を返します。 リストが 9 倍違うという事実こそ、 「外れ値検出は手法選択で答えが変わる」ことの動かぬ証拠です。

落とし穴 — マスキングと閾値の任意性

マスキング(masking):z スコアは平均と標準偏差を分母・分子に使いますが、 その平均(265 万人)と標準偏差(約 280 万人)自身が東京都に膨らまされています。 膨れた標準偏差のせいで境界が高く押し上げられ、 神奈川(約 923 万人)や大阪(約 876 万人)ですら |z| が 3 に届かず見逃されます。 一方、 中央値・MAD ベース(IQR / 修正 z)は外れ値自身に汚染されないため 9 県を捕捉します。 「極端な 1 点が、 他の外れ値を自分の陰に隠す」——これがマスキングです。

境界の任意性:同じ z スコア法でも閾値を |z|>2 にすると 3 県、 |z|>3 にすると 1 県。 「どこで線を引くか」だけで結論が 3 倍変わります。 閾値は自然法則ではなく約束事にすぎません。 だからこそ、 採用した基準・閾値・件数・県名を必ず明記し、 除外前後で結論が変わるかを感度分析する透明性が要になります(詳しくは 外れ値処理)。

発展 — 頑健化の「はしご」を実測値で

総人口 A1101(2023 年・47 県)の中心をどう測るか 素の平均 ≈ 265 万人 ← 東京都に最も引きずられる Winsorize(5%) 後平均 ≈ 253 万人 ← 上下 5% を境界値で置換 トリム平均(10%) ≈ 211 万人 ← 上下 10% を捨てて平均 中央値 ≈ 155 万人 ← 外れ値に最も頑健

外れ値を「消す(削除)」以外に、 影響を薄める選択肢があります。 Winsorization(極値を分位点の値で置き換える)やトリム平均(上下の一定割合を捨てる)は、 削除の恣意性を避けつつ頑健性を得る中間解です。 上のはしごは「どこまで外れ値の口出しを許すか」の連続的なダイヤルであり、 目的に応じて段を選びます。 さらに前処理を挟まず頑健推定そのものを使うなら 頑健統計(中央値・MAD・Huber 回帰)へ、 分布仮定を置かない多変量・非線形の検出なら Isolation Forest・LOF などの異常検知(本ページ「Python 実装」節参照)へ進みます。

発展 — 多変量では顔ぶれが入れ替わる(Mahalanobis)

総人口 1 変数ではなく、 総人口 A1101・出生数 A4101・転入者数 A5101 の 3 変数で Mahalanobis 距離を測ると($\chi^2_{3,\,0.975} \approx 9.35$ を境界)、 距離の大きい順は 東京(34.2)>北海道(19.9)>愛知(18.4)>大阪(11.2) の 4 県が境界超え。 注目すべきは神奈川(6.8)が境界内に沈むこと——総人口の単変量 IQR では外れ値だった県が、 出生・転入との関係の中では「人口相応」で埋もれます。 逆に北海道は総人口の z スコア(|z|>3)では拾えないのに、 多変量では 2 位に浮上します。 各変数では見えない/各変数では見えるはずが見えなくなる——多変量外れ値の両面性が実データで確認できます(Mahalanobis 距離・共分散を考慮した多変量距離)。

🔗 関連ページ

この補足と合わせて読むと理解が深まるページ: 箱ひげ図(IQR フェンスの可視化) / 四分位範囲(IQR)MAD中央値標準偏差標準化・z スコア頑健統計外れ値処理分位点。 * z スコア専用ページ・Mahalanobis 距離専用ページ・異常検知(anomaly detection)専用ページ・Winsorization 専用ページは現時点で未作成のため、 それぞれ本ページ内の該当節と上記の関連ページを参照してください。