論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
四分位
Quartile (Q1/Q2/Q3)
データを大小順に並べて4等分する3つの値。Q1=25%点、Q2=中央値、Q3=75%点。箱ひげ図の基礎。
記述統計Q1/Q2/Q3パーセンタイルQ1Q3

🔖 キーワード索引

「quartile」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「quartile」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

quartile統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「quartile の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30秒で分かる結論

🍰 まずはやさしく

データを4等分する3つの区切り点のことです。

データの広がりを正しく知るために使います。

テストの点数を順番に並べて分けるイメージです。

ここでは四分位の定義と使い方を学びます。

📖 もっと詳しく

四分位(quartile)は、 データを大小順に並べて4等分する3つの値。 Q1 = 25%点、 Q2 = 中央値、 Q3 = 75%点と呼びます。

四分位範囲(IQR) = Q3 − Q1。 真ん中50%のデータの広がりを表す「ロバストな広がり指標」(外れ値に影響されにくい)。

使い道:

Python:df.quantile([0.25, 0.5, 0.75]) または df.describe() で一発取得。

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

📍 学習の3ステップ

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

🔧 Python実装パターン

🎯 目的:SSDSE-B-2026 を読み込み、describe で四分位数(25%/50%/75%)を一覧表示する四分位の入門パターン。
📥 入力:data/raw/SSDSE-B-2026.csv(cp932, header=1 で日本語列名)。564 行(47 都道府県 × 12 年度)から 2023 年度の 47 行に絞り、食料費・教育費・住居費(二人以上の世帯、円/月)の 3 列を使う。
1
2
3
4
5
6
7
8
9
10
11
# 基本パターン: 2023 年度の 47 都道府県に絞り、describe で四分位を一覧表示する
import pandas as pd

# データ読み込み(header=1 で 2 行目の日本語列名を使う)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
df23 = df[df['年度'] == 2023]   # 47 都道府県 × 12 年度 = 564 行から 2023 年度の 47 行へ
print('rows:', len(df23))

# 基本統計量(25% / 50% / 75% が Q1 / Q2 / Q3)
cols = ['食料費(二人以上の世帯)', '教育費(二人以上の世帯)', '住居費(二人以上の世帯)']
print(df23[cols].describe().round(0).to_string())
📤 出力 rows: 47 食料費(二人以上の世帯) 教育費(二人以上の世帯) 住居費(二人以上の世帯) count 47.0 47.0 47.0 mean 80598.0 9577.0 18361.0 std 5842.0 4212.0 4333.0 min 71088.0 4316.0 11639.0 25% 76014.0 6730.0 14608.0 50% 79939.0 8554.0 18473.0 75% 85088.0 11420.0 20737.0 max 97776.0 24160.0 27521.0
💬 解説:25%・50%・75% の行がそのまま Q1・Q2・Q3。食料費は Q1 76,014 円・Q3 85,088 円で IQR は約 9,075 円、教育費は 6,730〜11,420 円で IQR 4,690 円と金額は小さいが、最大の東京都 24,160 円は Q3 の 2 倍を超えて右に長く伸びる。住居費は最大が沖縄県 27,521 円、最小が神奈川県 11,639 円で、都市ほど高いという直感が当てはまらないので、四分位だけでなくどの県が端にいるかも確かめる。

📚 四分位の概念マップでの位置

四分位 (Q1/Q2/Q3) は順序統計量から派生する位置の要約量。 上位カテゴリは分位点 (Quantile)で、 q=0.25, 0.5, 0.75 の特別な場合に相当する。 並列概念はパーセンタイル (1〜99 の任意点) と五数要約 (min, Q1, Q2, Q3, max)。 派生として箱ひげ図、 IQR、 IQR×1.5 ルールでの外れ値検出が広く使われる。

🎯 SSDSE-B-2026 で挑戦する四分位の課題

47 都道府県の家計支出・人口データを使い、 四分位そのものの計算と読み取りに集中して練習する。

💡 四分位計算でよく使うコマンド集

機能 Python (pandas) Python (numpy / scipy)
Q1 (25%)df.quantile(0.25)np.percentile(x, 25)
中央値 Q2df.median()np.median(x)
Q3 (75%)df.quantile(0.75)np.percentile(x, 75)
IQRdf.quantile(.75)-df.quantile(.25)scipy.stats.iqr(x)
五数要約df.describe()np.percentile(x,[0,25,50,75,100])
箱ひげ図df.boxplot()matplotlib.pyplot.boxplot(x)
補間方式の指定df.quantile(.25, interpolation='linear')np.percentile(x,25,method='linear')

🚧 四分位の落とし穴と対策

📊 四分位の結果報告フォーマット

🌐 四分位が活きる分野

🎓 四分位をさらに学ぶための文献

🔗 四分位を理解するための関連用語ネットワーク

四分位は「分位点」「順序統計量」「ロバスト統計」「可視化」の交差点に位置する。 以下の概念を併せて学ぶと理解が安定する。

四分位を学ぶ上で押さえたい概念グループ

グループ 四分位と関連の深い概念
前提順序統計量、 累積分布関数 CDF、 補間 (linear/midpoint/lower)
並列 (位置の要約)中央値 Q2、 パーセンタイル、 トリム平均、 ヒンジ (Tukey 由来)
派生 (ばらつき)IQR、 五数要約、 MAD (中央絶対偏差)、 SIQR
可視化箱ひげ図、 ヴァイオリンプロット、 Q-Q プロット
外れ値判定Tukey の 1.5×IQR、 3×IQR、 ロバスト z スコア
対比される指標平均、 標準偏差、 分散 (外れ値に弱い)
発展 (回帰)分位点回帰、 ピンボール損失
応用 (リスク)VaR、 CVaR、 信頼区間の代替としてのブートストラップ分位点
分布論歪度、 尖度、 経験分布
機械学習分位点ロス、 LightGBM の quantile objective

四分位を中心とした学習順序の推奨

  1. 順序統計量と CDF の感覚を掴む (n 個並べて p×n 番目の値)
  2. 中央値 Q2 → Q1, Q3 へと拡張する
  3. IQR と五数要約を計算し、 箱ひげ図で可視化
  4. 補間方式 (linear / midpoint / lower) の違いを 6 値程度の小データで確認
  5. Tukey の 1.5×IQR ルールで外れ値を定義し、 SSDSE-B の都道府県で実演
  6. 分位点全般 (パーセンタイル、 デシル、 VaR) に拡張
  7. 分位点回帰 (Koenker) で条件付き四分位を推定する応用へ

📝 四分位の実践練習 — SSDSE-B-2026

初級課題 (四分位の計算)

  1. 47 都道府県の食料費の Q1, Q2, Q3 を df.quantile([.25,.5,.75]) で算出
  2. 食料費の箱ひげ図を描き、 Q1, Q3, ひげの位置を読み取る
  3. interpolation='linear' と 'midpoint' で Q1 が変わるか比較
  4. 東京・大阪・愛知が Q3 を超えているか判定

中級課題 (IQR と外れ値)

  1. 家計支出 5 項目 (食料・住居・教育・交通・通信) の IQR を並べ、 ばらつきの大きい項目を特定
  2. Q1−1.5·IQR / Q3+1.5·IQR の外側にある都道府県を抽出 (Tukey ルール)
  3. 同じ外れ値検出を「平均 ± 2SD」でも行い、 抽出される県を比較
  4. 食料費を 10 分位 (デシル) に分け、 都道府県をランク付け

上級課題 (分位点ベースのモデリング)

  1. 家計データを bootstrap 再標本し、 Q1/Q3 の 95% 信頼区間を求める
  2. 地域 (北海道・東北・関東・中部・近畿・中国・四国・九州) ごとに食料費の四分位を比較し、 boxplot で並べる
  3. 分位点回帰 (statsmodels.QuantReg) で食料費を Q1/Q2/Q3 ごとに予測
  4. 外れ値判定を IQR ルール / ロバスト z / Mahalanobis 距離で行い、 一致率を計算

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

🍰 まずはやさしく

データを4つのグループに分ける値のことです。

極端な値に惑わされずに分析するために使います。

都道府県ごとの人口などのデータで考えます。

計算方法と外れ値の判定について読みましょう。

論文中に 「四分位」として登場する用語。

四分位 とは:データを大小順に並べて4等分する3つの値。Q1=25%点、Q2=中央値、Q3=75%点。箱ひげ図の基礎。

本ページの主目的は「SSDSE-B-2026 の 47 都道府県データ (総人口・出生数・消費支出) を題材に、 Q1=25%点・Q2=中央値・Q3=75%点を手計算と NumPy/Pandas で一致させる」ことである。 平均と異なり外れ値 (東京・鳥取) に影響されにくい点が中央値・四分位の強みとなる。

後段では (1) ソート後に位置 (n+1)/4, (n+1)/2, 3(n+1)/4 を求め線形補間、 (2) numpy.quantile の 9 種の補間方式 (linear / lower / nearest など) の違い、 (3) IQR = Q3 − Q1 と外れ値判定 1.5×IQR の実例を扱う。

🎨 直感で掴む — 四分位 の本質

🍰 まずはやさしく

データを4等分する境界線のことです。

真ん中あたりのデータの範囲を見るために使います。

お小遣いの金額を並べて分けるときのようなものです。

まずは道具としての使い道を直感的に掴みましょう。

四分位はデータを小さい順に並べて4 等分した区切り点。 Q1(25%)、 Q2(中央値)、 Q3(75%)。 SSDSE-B-2026 の消費支出(L3221、二人以上の世帯・月額)47 県を昇順に並べると、 Q1 ≈ 26.5 万、 中央値 ≈ 28 万、 Q3 ≈ 30.5 万。 平均値だけでなく Q1-Q3 で「真ん中の半分の範囲」が見えるのが四分位の強み。

💡 ポイント:四分位 を初めて学ぶときは「正確な定義」より「どんな問題を解くための道具か」を先に押さえてください。 数式は次の「📐 数式」セクションで丁寧に展開します。
📌 比喩がうまく刺さらないときは、 自分の身近な例(家計簿・スポーツの記録・成績表)に置き換えてみると理解が定着します。 SSDSE-B-2026 を電卓代わりに触りながら、 上の説明を再読すると効果的です。

🎨 概念図で押さえる

四分位の定義と使い方を、 3 点のインライン SVG で押さえる。

図1 四分位の定義

四分位の定義

Q1=下位 25%、 Q2=中央値=50%、 Q3=上位 25%(=下位 75%)。 データを 4 等分する境界点。

図2 IQR と外れ値判定

IQRと外れ値

IQR=Q3-Q1 はばらつき指標。 ひげの外側に出た点が外れ値候補。

図3 四分位による分布形状の判定

四分位による分布判定

中央値が箱の中央にある=対称、 偏っていれば歪んだ分布。 平均と中央値の差で歪度を直感把握。

📝 理解度チェック

  1. Q1 はデータの何%地点? (答:25%/第1四分位数)
  2. IQR の定義は? (答:Q3-Q1)
  3. 1.5×IQR ルールでの外れ値判定の上限値は? (答:Q3+1.5×IQR)
  4. 四分位は外れ値に強い? (答:はい。 順位ベースなのでロバスト)
  5. numpy.percentile と pandas.quantile では計算法が複数あるが、 デフォルトは? (答:linear/type 7)

🎮 触って理解する — 四分位を動かす

下の数直線上の点をドラッグ(スマホは指でスワイプ)すると、 Q1・Q2(中央値)・Q3・IQR がリアルタイムに再計算され、 縦線と色分け領域・箱ひげ図・外れ値フェンス(Q1−1.5×IQR / Q3+1.5×IQR)が連動して更新されます。 中央付近の点を動かしても四分位はあまり動かず、 端の点を大きく動かしても中央値・IQR がびくともしない——この頑健性(ロバスト性)を、 同時に表示される平均値・標準偏差の激しい動きと見比べて体感してください。

データ例:

操作: 点をドラッグで移動 / 数直線上の空き部分をクリック/タップで点を追加 / 点をダブルクリックで削除(最少3点)。

四分位(順位ベース・頑健)
n = - 個(単位: -)
Q1 (25%) = - Q2 (中央値) = - Q3 (75%) = -
IQR = Q3 − Q1 = -
下側フェンス = - 上側フェンス = -
外れ値: -
平均・SD(外れ値に弱い)
平均 = -
標準偏差 = -
端の点をドラッグすると平均とSDは大きく動くが、 中央値とIQRはほぼ不変——これが四分位のロバスト性。

📖 このデモで確かめられること

📐 数式または定義 — 四分位 の形式的表現

🍰 まずはやさしく

データを4等分する値を数式で表したものです。

正確な値を計算するために使います。

部活の記録を正確に分析するときに役立ちます。

記号の意味と計算の手順について詳しく読みましょう。

直感で全体像を掴んだら、 次は厳密な定義を見ます。 数式は短いものでも、 「何を入力にして、 何を出力するのか」を意識して読むと早く慣れます。

【四分位と IQR(四分位範囲)】
$$ Q_k = x_{(\lceil k n / 4 \rceil)} \quad (k=1,2,3) \qquad \mathrm{IQR} = Q_3 - Q_1 $$
この数式は「四分位 がどう計算されるか」を最短で示したもの。 記号の意味は次の「🔬 数式を言葉で読み解く」で 1 つずつ解説します。
📚 数式が苦手な方へ:1 つの長い式を一度に理解しようとせず、 記号ごとに「言葉に翻訳」するのが王道。 紙に書き写してから、 自分の言葉で音読してみてください。

📐 補間方法 9 種類の比較 — 同じデータでも Q25/Q75 が変わる

四分位数の計算は「順序統計量 (sorted data) のどの位置を取り出すか」という問題に帰着する。 ところが、 整数番目に該当しない位置 (例: 12.25 番目) をどう補間するかで複数の流儀がある。 NumPy 1.22 以降は numpy.quantile に 9 種類の method 引数があり、 統計教科書ごとに採用流儀が異なるため、 結果が微妙に異なる。

🔬 数式を言葉で読み解く — 補間の一般式

サンプル数 n、 求めたい分位点 q ∈ [0,1] に対し、 「仮想的な順位」 h = (n - α - β + 1) q + α を計算する (α, β は方法ごとに決まる定数)。 h の整数部 j、 小数部 g として、 結果は (1-g) × x_{(j)} + g × x_{(j+1)} となる。 つまり「ソート済みデータの第 j 番目と第 j+1 番目を g : (1-g) で按分する」だけ。 9 種類の方法の違いは α, β の値の違いだけだ。

methodαβ典型用途特徴
linear (既定)11R type 7、 NumPy 標準連続分布の標本に最適
lower−−離散値のみ小さい側に丸める
higher−−離散値のみ大きい側に丸める
nearest−−最近傍法隣接 2 点の近い方
midpoint−−中央 2 点平均単純で頑健
weibull00SAS type 4経験分布関数の逆
median_unbiased1/31/3中央値の不偏推定分布によらず中央バイアス除去
normal_unbiased3/83/8正規分布で不偏正規仮定下で最適
averaged_inverted_cdf−−SAS type 2不連続点で平均

→ 報告書では「補間方法: linear (NumPy 既定 / R type 7)」のように明示することが推奨される。 行政統計や論文では Excel の QUARTILE.INC が linear、 QUARTILE.EXC が weibull に対応する点も覚えておくと、 「Excel と Python で値が違う」という典型ミスを避けられる。

🔬 数式を言葉で読み解く — 四分位 の記号辞書

上の四分位の定義式・線形補間式に出てくる各記号が何を表すかを、 言葉・読み方・SSDSE-B-2026 (47 都道府県データ) での具体例の 3 段で翻訳します。 1 つずつ自分の言葉で言い換えられるようになると、 論文や教科書のスピードが一気に上がります。

記号読み方意味SSDSE-B-2026 47 都道府県での例
$n$エヌ (sample size)データの個数。 並べる対象の総数。$n = 47$ (47 都道府県)
$x_{(i)}$エックス カッコ アイ (order statistic)昇順ソート後の $i$ 番目の値。 順序統計量。 $x_{(1)}$ が最小、 $x_{(n)}$ が最大。食料費(月額)なら $x_{(1)}=$ 愛媛県 71,088 円、 $x_{(47)}=$ 東京都 97,776 円
$q$キュー (quantile fraction)分位の比率。 $0 \le q \le 1$。 四分位なら $q = 0.25, 0.5, 0.75$。$q=0.25$ は「下から 25%」の位置
$Q_1$キューワン (first quartile)第 1 四分位。 下から 25% の位置の値。 $q=0.25$ の分位点。食料費 $Q_1 \approx 76{,}000$ 円
$Q_2$キューツー (median)第 2 四分位 = 中央値。 下から 50% の位置。食料費 $Q_2 \approx 80{,}000$ 円 (24 番目の県)
$Q_3$キュースリー (third quartile)第 3 四分位。 下から 75% の位置の値。 $q=0.75$ の分位点。食料費 $Q_3 \approx 85{,}000$ 円
IQRアイキューアール (Interquartile Range)四分位範囲 = $Q_3 - Q_1$。 中央 50% の幅。 外れ値に強い「ばらつき」指標。IQR $\approx 85{,}000 - 76{,}000 = 9{,}000$ 円
$h$ (補間位置)エイチ$Q_1$ などが整数番目に来ないときの「小数位置」。 NumPy 既定 (linear / R type 7) では $h = (n-1) \cdot q + 1$。$n=47, q=0.25$ → $h = 46 \cdot 0.25 + 1 = 12.5$ (12 番目と 13 番目の中間)
$\lfloor h \rfloor, \lceil h \rceil$フロアエイチ / シーリングエイチ$h$ を切り捨てた整数 / 切り上げた整数。 補間に使う両端のインデックス。$h=12.5$ → $\lfloor h \rfloor = 12, \lceil h \rceil = 13$
$1.5 \cdot$ IQRいってんごばい アイキューアール外れ値判定の係数。 Tukey の経験則。 $Q_1 - 1.5\cdot$IQR 未満 or $Q_3 + 1.5\cdot$IQR 超を外れ値とする。外れ値境界 $\approx [62{,}500, 98{,}500]$ 円
📌 数式の読み下し:「データを昇順に並べて ($x_{(1)} \le \cdots \le x_{(n)}$)、 下から $25\%, 50\%, 75\%$ の位置にある値が $Q_1, Q_2, Q_3$。 ぴったり整数番目に来ない時は、 補間位置 $h$ を求めて両隣の値の線形補間を取る」。 ポイントは ① $Q_2$ = 中央値、 ② IQR で「中央 50%」の散らばりを測る、 ③ $1.5\cdot$IQR で外れ値を判定する、 の 3 つです。

🧮 SSDSE-B 実値計算例:47都道府県データの四分位

SSDSE-B-2026 2023年データで、 47都道府県の食料費(L322101、二人以上の世帯・月額)の四分位を計算します。

📊 ステップ1:四分位の実値

統計量 食料費(円/世帯・月) 代表的な県
最小値71,088愛媛県
Q1(25%点)76,014福井県 75,825 と群馬県 76,203 の中間(12.5 番目)
Q2(中央値)79,939熊本県(24 番目)
Q3(75%点)85,088.5大阪府 85,042 と静岡県 85,135 の中間(35.5 番目)
最大値97,776東京都

IQR = Q3 - Q1 = 85,088.5 - 76,014 = 9,074.5円。 真ん中50%(24 県分)が約 9,075 円幅に収まる。 標準偏差は約 5,842 円で、 IQR はその約 1.55 倍(正規分布なら 1.349 倍)。 IQR が SD に比べてやや大きいのは、 分布の中央部が平らに広がっていることを示す。

📊 ステップ2:Tukey 基準の外れ値判定

SSDSE 2023 のデータでは最小の愛媛県(71,088 円)も最大の東京都(97,776 円)もフェンスの内側で、 外れ値の県は無い。 ただし東京都は上側フェンスまで 924 円しか余裕がなく、 2 位の埼玉県(93,279 円)とも 4,500 円近く離れている。

📊 ステップ3:歪度の確認

(Q3-Q2) と (Q2-Q1) を比較すると、 分布の歪みが分かる:

🧮 実値で計算してみる — SSDSE-B-2026 で 四分位 を体感

数式だけでは「分かった気になる」だけで終わりがち。 ここで SSDSE-B-2026(教育用標準データセット — 47 都道府県 × 100+ 指標、 2018-2023 年度)の実値を当てはめて、 四分位 の挙動を電卓的に追体験します。

👉 計算例:SSDSE-B-2026(2023)の 47 都道府県の大学卒業者数(E6502)は最小 約 1500(鳥取)、 Q1 ≈ 2600、 中央値 ≈ 4000、 Q3 ≈ 10000、 最大 約 16 万(東京)。 IQR ≈ 7500、 外れ値の上限ライン Q3+1.5×IQR ≈ 21300。 東京(約 16 万)はこのラインを大きく超え、 統計的に「外れ値」と判定される。

SSDSE-B-2026 は 統計センターの SSDSE 配布ページ から CSV を直接ダウンロードできます。 本サイトでは data/raw/SSDSE-B-2026.csv に配置している前提でコードを書いています。

🧮 SSDSE-B-2026 47 県人口で四分位数を実計算

このコードでやること: SSDSE-B-2026 の A1101 総人口(人) 2023 年度 47 県分について、 4 種類の補間方法で Q25/Q50/Q75 を並べ、 同じデータでも値がどう変わるかを比較する。

📥 入力データ (SSDSE-B-2026 抜粋、 47 県):

SSDSE-2026 都道府県 A1101 総人口(人) R01000 北海道 5,092,000 R02000 青森県 1,184,000 R03000 岩手県 1,163,000 R04000 宮城県 2,264,000 ... ... ... R47000 沖縄県 1,468,000 (47 行 × 数百カラム のうち A1101 列を使用)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
pop = df.groupby('Prefecture')['A1101'].first().sort_values()

methods = ['linear', 'lower', 'higher', 'midpoint']
print(f'{"method":<12} {"Q25":>10} {"Q50":>10} {"Q75":>10} {"IQR":>10}')
for m in methods:
    q25, q50, q75 = np.quantile(pop, [0.25, 0.50, 0.75], method=m)
    print(f'{m:<12} {q25:>10.2f} {q50:>10.2f} {q75:>10.2f} {q75-q25:>10.2f}')

📤 実行すると次の出力が得られる:

method Q25 Q50 Q75 IQR linear 1034000.00 1549000.00 2636500.00 1602500.00 lower 1026000.00 1549000.00 2535000.00 1509000.00 higher 1042000.00 1549000.00 2738000.00 1696000.00 midpoint 1034000.00 1549000.00 2636500.00 1602500.00

💬 結果の読み方: 単位は人(A1101 の生値)。 Q50 (中央値) は 4 方式とも同じ 1,549,000 人 (N=47 で 24 番目にあたる県)。 一方 Q25 は 1,026,000〜1,042,000 人、 Q75 は 2,535,000〜2,738,000 人と補間方法で 最大 20 万人ブレる。 IQR (四分位範囲) も 1,509,000 〜 1,696,000 人と約 19 万人差。 「同じデータでも方式次第で結論が変わる」典型例。 報告では必ず method='linear' 等を明示することが必要。

🧮 数式に値を入れて手で計算する: 四分位数

合成 8 件データで Q1, Q2, Q3 を計算する。

Step 1: ソート

x = [3, 5, 7, 8, 10, 12, 15, 18] n=8

Step 2: 四分位

Q1 = (5+7)/2 = 6 Q2 (中央値) = (8+10)/2 = 9 Q3 = (12+15)/2 = 13.5

🐍 Python で再現

1
2
3
4
5
6
7
8
import numpy as np
x = np.array([3, 5, 7, 8, 10, 12, 15, 18])
# 手計算と同じ「隣り合う 2 値の平均」は method='midpoint'
q_mid = np.percentile(x, [25, 50, 75], method='midpoint')
print(f"midpoint: Q1: {q_mid[0]}, Q2: {q_mid[1]}, Q3: {q_mid[2]}")
# numpy の既定 method='linear' は位置 (n-1)p で線形補間するので値が変わる
q_lin = np.percentile(x, [25, 50, 75])
print(f"linear  : Q1: {q_lin[0]}, Q2: {q_lin[1]}, Q3: {q_lin[2]}")

📤 実行結果

midpoint: Q1: 6.0, Q2: 9.0, Q3: 13.5 linear : Q1: 6.5, Q2: 9.0, Q3: 12.75

💬 method='midpoint' の Q1=6.0・Q2=9.0・Q3=13.5 は Step 2 の手計算と完全に一致する。numpy 既定の linear は位置 (n−1)p = 1.75, 5.25 で補間するので Q1=6.5・Q3=12.75 になり、Q2=9.0 だけはどちらでも同じ。手計算と照合するときは method を揃える。

🐍 Python 実装バリエーション

① numpy.percentile / numpy.quantile

🎯 目的:1 次元配列に対し numpy.percentile / numpy.quantile で四分位数を厳密に計算する最も基本的な API。
📥 入力:arr(1 次元数値配列)、パーセンタイル指定(25, 50, 75)。
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
# ── この抜粋で使うデータを用意します(SSDSE-B の 47 都道府県・最新年度)──
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
df = df[df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy()
df['年度'] = pd.to_numeric(df['年度'], errors='coerce')
df = df[df['年度'] == df['年度'].max()]
for _c in df.columns[3:]:
    df[_c] = pd.to_numeric(df[_c], errors='coerce')
df['高齢化率'] = df['65歳以上人口'] / df['総人口'] * 100

# 見本でよく使われる仮の列名を、実データから作っておく
df['income'] = df['消費支出(二人以上の世帯)']
df['population'] = df['総人口']
_region = {'北海道': '北海道', '青森県': '東北', '岩手県': '東北', '宮城県': '東北',
           '秋田県': '東北', '山形県': '東北', '福島県': '東北', '茨城県': '関東',
           '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東',
           '東京都': '関東', '神奈川県': '関東'}
df['region'] = df['都道府県'].map(_region).fillna('その他')
df['地域'] = df['region']
import numpy as np
q1, q2, q3 = np.percentile(df['income'], [25, 50, 75])
print('Q1, Q2, Q3 :', q1, q2, q3)
# method(旧 interpolation)を指定可能
q1 = np.percentile(df['income'], 25, method='linear')
print('Q1 linear  :', q1)
print('Q1 lower   :', np.percentile(df['income'], 25, method='lower'))
print('Q1 higher  :', np.percentile(df['income'], 25, method='higher'))
📤 出力 Q1, Q2, Q3 : 279506.0 300652.0 307501.5 Q1 linear : 279506.0 Q1 lower : 279132 Q1 higher : 279880
💬 解説:2023 年度 47 都道府県の消費支出(二人以上の世帯、円/月)は Q1 279,506 円・中央値 300,652 円・Q3 307,501.5 円。Q1 の位置は 46×0.25 = 11.5 番目(0 始まり)なので、lower は 279,132 円、higher は 279,880 円と 12 番目・13 番目の県の値そのものになり、linear はその中点を返す。method を変えても差は 748 円の範囲に収まるが、pandas の quantile と数値が違うときはまずこの引数を疑う。

② pandas df.quantile / df.describe()

🎯 目的:DataFrame に対し df.quantile() / df.describe() で複数列の四分位数を一括計算するパンダス標準パターン。
📥 入力:df['income'](Series)または DataFrame、パーセンタイルのリスト。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ── この抜粋で使うデータを用意します(SSDSE-B の 47 都道府県・最新年度)──
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
df = df[df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy()
df['年度'] = pd.to_numeric(df['年度'], errors='coerce')
df = df[df['年度'] == df['年度'].max()]
for _c in df.columns[3:]:
    df[_c] = pd.to_numeric(df[_c], errors='coerce')
df['高齢化率'] = df['65歳以上人口'] / df['総人口'] * 100

# 見本でよく使われる仮の列名を、実データから作っておく
df['income'] = df['消費支出(二人以上の世帯)']
df['population'] = df['総人口']
_region = {'北海道': '北海道', '青森県': '東北', '岩手県': '東北', '宮城県': '東北',
           '秋田県': '東北', '山形県': '東北', '福島県': '東北', '茨城県': '関東',
           '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東',
           '東京都': '関東', '神奈川県': '関東'}
df['region'] = df['都道府県'].map(_region).fillna('その他')
df['地域'] = df['region']

print(df['income'].quantile([0.25, 0.5, 0.75]))
print(df.describe())  # count, mean, std, min, 25%, 50%, 75%, max
📤 出力 0.25 279506.0 0.50 300652.0 0.75 307501.5 Name: income, dtype: float64 年度 総人口 ... income population count 47.0 4.700000e+01 ... 47.000000 4.700000e+01 mean 2023.0 2.645809e+06 ... 295856.021277 2.645809e+06 std 0.0 2.797551e+06 ... 24144.057036 2.797551e+06 min 2023.0 5.370000e+05 ... 223423.000000 5.370000e+05 25% 2023.0 1.034000e+06 ... 279506.000000 1.034000e+06 50% 2023.0 1.549000e+06 ... 300652.000000 1.549000e+06 75% 2023.0 2.636500e+06 ... 307501.500000 2.636500e+06 max 2023.0 1.408600e+07 ... 344092.000000 1.408600e+07 [8 rows x 113 columns]
💬 解説:quantile の 279,506 / 300,652 / 307,501.5 円は、describe の income 列の 25%・50%・75% 行と同じ値。describe は 113 列すべてを返し途中が「...」で省略されるので、四分位だけ欲しいときは quantile で列を指定する方が読みやすい。総人口は平均 264.6 万人が中央値 154.9 万人を大きく上回り、右に長い分布であることもこの表から分かる。

③ scipy.stats(iqr / scoreatpercentile)

🎯 目的:外れ値検出に使う四分位範囲(IQR = Q3 − Q1)を scipy.stats.iqr で 1 行計算するコード。
📥 入力:arr(数値配列)、interpolation や axis オプション。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ── この抜粋で使うデータを用意します(SSDSE-B の 47 都道府県・最新年度)──
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
df = df[df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy()
df['年度'] = pd.to_numeric(df['年度'], errors='coerce')
df = df[df['年度'] == df['年度'].max()]
for _c in df.columns[3:]:
    df[_c] = pd.to_numeric(df[_c], errors='coerce')
df['高齢化率'] = df['65歳以上人口'] / df['総人口'] * 100

# 見本でよく使われる仮の列名を、実データから作っておく
df['income'] = df['消費支出(二人以上の世帯)']
df['population'] = df['総人口']
_region = {'北海道': '北海道', '青森県': '東北', '岩手県': '東北', '宮城県': '東北',
           '秋田県': '東北', '山形県': '東北', '福島県': '東北', '茨城県': '関東',
           '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東',
           '東京都': '関東', '神奈川県': '関東'}
df['region'] = df['都道府県'].map(_region).fillna('その他')
df['地域'] = df['region']

from scipy.stats import iqr, scoreatpercentile
print(iqr(df['income']))  # IQR
print(scoreatpercentile(df['income'], 25))  # Q1
📤 出力 27995.5 279506.0
💬 解説:消費支出の IQR は 27,995.5 円、Q1 は 279,506 円で、numpy の linear と同じ値になる。Tukey の 1.5×IQR ルールを当てると下側フェンスは 237,512.75 円、上側フェンスは 349,494.75 円で、外に出るのは愛媛県(223,423 円)の 1 県だけ。最大の埼玉県 344,092 円はフェンスの内側に収まる。

④ scikit-learn — RobustScaler(IQR で標準化)

外れ値に強い標準化として、 平均/SD ではなく中央値/IQR を使う。

🎯 目的:外れ値の影響を受けにくい RobustScaler(中央値で中心化、IQR でスケーリング)で SSDSE-B-2026 の支出データを標準化する。
📥 入力:X(DataFrame または ndarray、外れ値を含み得る)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# ── この抜粋で使うデータを用意します ──
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]          # 2023 年の 47 都道府県
X = df[['A1101', 'A1303', 'L3221']].astype(float).values
y = df['A4101'].astype(float).values          # 出生数
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42)

from sklearn.preprocessing import RobustScaler
# (x - Q2) / IQR でスケーリング
scaler = RobustScaler().fit(X)
X_robust = scaler.transform(X)
print('中央値 (center_):', scaler.center_)
print('IQR    (scale_) :', scaler.scale_)
print('変換後の中央値  :', np.median(X_robust, axis=0).round(3))
q1, q3 = np.percentile(X_robust, [25, 75], axis=0)
print('変換後の IQR    :', (q3 - q1).round(3))
print('変換後の最大値  :', X_robust.max(axis=0).round(2))
📤 出力 中央値 (center_): [1549000. 524000. 300652.] IQR (scale_) : [1602500. 438500. 27995.5] 変換後の中央値 : [0. 0. 0.] 変換後の IQR : [1. 1. 1.] 変換後の最大値 : [7.82 6.11 1.55]
💬 解説:center_ は総人口 154.9 万人・65 歳以上人口 52.4 万人・消費支出 300,652 円の中央値、scale_ はそれぞれの IQR で、変換後は中央値 0・IQR 1 に揃う。ただし最大値は総人口で 7.82、65 歳以上人口で 6.11 と、東京都は変換後も IQR の 6〜8 倍離れたまま残る。RobustScaler は物差しを外れ値に引っ張られないようにするだけで、外れ値そのものを縮めはしない。

⑤ matplotlib / seaborn — 箱ひげ図

🎯 目的:SSDSE-B-2026 の都道府県別データを箱ひげ図で可視化し、Q1/中央値/Q3/ひげ/外れ値を一目で把握する。
📥 入力:df(DataFrame)、x(カテゴリ列、例:地方区分)、y(数値列、例:消費支出)。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# ── この抜粋で使うデータを用意します(SSDSE-B の 47 都道府県・最新年度)──
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
df = df[df['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)].copy()
df['年度'] = pd.to_numeric(df['年度'], errors='coerce')
df = df[df['年度'] == df['年度'].max()]
for _c in df.columns[3:]:
    df[_c] = pd.to_numeric(df[_c], errors='coerce')
df['高齢化率'] = df['65歳以上人口'] / df['総人口'] * 100

# 見本でよく使われる仮の列名を、実データから作っておく
df['income'] = df['消費支出(二人以上の世帯)']
df['population'] = df['総人口']
_region = {'北海道': '北海道', '青森県': '東北', '岩手県': '東北', '宮城県': '東北',
           '秋田県': '東北', '山形県': '東北', '福島県': '東北', '茨城県': '関東',
           '栃木県': '関東', '群馬県': '関東', '埼玉県': '関東', '千葉県': '関東',
           '東京都': '関東', '神奈川県': '関東'}
df['region'] = df['都道府県'].map(_region).fillna('その他')
df['地域'] = df['region']

import seaborn as sns
sns.boxplot(data=df, x='region', y='income', whis=1.5)
# whis=1.5 で Tukey fence、 whis='range' で min-max
📤 出力 x ごとの箱ひげ図画像(中央値・四分位範囲・外れ値が黒点)。
💬 解説:2023 年度の消費支出では、関東 7 都県の中央値 307,817 円が「その他」33 県の 297,715 円より高いが、関東の中に Tukey の外れ値は無い。外れ値の黒点が出るのは「その他」の愛媛県(223,423 円)だけで、北海道は 1 県しかないので箱にならず線 1 本になる。区分に「その他」33 県をまとめているため、violinplot に切り替えたり区分を細かくしたりして中身を確かめる。

🐍 Python 実装 — 四分位 を SSDSE-B-2026 で動かす

🎯 このコードでやること: 47 都道府県の総人口について、 Hyndman & Fan (1996) が整理した 6 通りの分位点定義で四分位数を計算し、 値がどれだけ食い違うかを並べます。 numpy の既定は type 7、 R の既定も type 7 ですが、 SPSS や Excel は別の定義を使います。 「四分位数」という同じ言葉で、 ソフトによって違う数字が出ることを実際の 47 県データで確かめます。 なお pd.read_csv('data/raw/SSDSE-B-2026.csv') をパス変数にせず直書きしているのは、 初学者が「パスをどこに書くべきか」で迷わないようにするためです。 CSV を同じ階層に置けばそのまま動きます。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 SSDSE-B-2026(年度) A4103(合計特殊出生率) A1101(総人口) 北海道 2,023 1.06 5,092,000 東京都 2,023 0.99 14,086,000 沖縄県 2,023 1.6 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
# 四分位 を SSDSE-B-2026 で確かめる最小コード
import pandas as pd
import numpy as np

# 1) SSDSE-B-2026(教育用標準データセット)を読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
print('shape:', df.shape)        # (564, 112) — 47 都道府県 × 12 年度(2012〜2023)

# 2) 直近年度(2023 年度)に絞る
df23 = df[df['年度'] == 2023].copy()
print('rows in 2023:', len(df23))
x = df23['総人口'].astype(float)

# 3) Hyndman & Fan (1996) の 6 定義で Q1・Q2・Q3 を計算して並べる
methods = {
    'type1 inverted_cdf':     'inverted_cdf',
    'type2 averaged_inv_cdf': 'averaged_inverted_cdf',
    'type5 hazen':            'hazen',
    'type6 weibull (SPSS, Excel .EXC)': 'weibull',
    'type7 linear (numpy/R, Excel .INC)': 'linear',
    'type8 median_unbiased':  'median_unbiased',
}
rows = {name: np.quantile(x, [0.25, 0.50, 0.75], method=m) for name, m in methods.items()}
res = pd.DataFrame(rows, index=['Q1', 'Q2', 'Q3']).T
res['IQR'] = res['Q3'] - res['Q1']
print('---- 四分位 結果(総人口, 人) ----')
print(res.round(0).astype(int).to_string())
print('Q3 の最大差:', int(res['Q3'].max() - res['Q3'].min()), '人')
📤 実行例(実測) shape: (564, 112) rows in 2023: 47 ---- 四分位 結果(総人口, 人) ---- Q1 Q2 Q3 IQR type1 inverted_cdf 1026000 1549000 2738000 1712000 type2 averaged_inv_cdf 1026000 1549000 2738000 1712000 type5 hazen 1030000 1549000 2687250 1657250 type6 weibull (SPSS, Excel .EXC) 1026000 1549000 2738000 1712000 type7 linear (numpy/R, Excel .INC) 1034000 1549000 2636500 1602500 type8 median_unbiased 1028667 1549000 2704167 1675500 Q3 の最大差: 101500 人

💬 同じ 47 県の総人口でも、Q1 は 102.6 万〜103.4 万人、Q3 は 263.65 万〜273.8 万人と定義によって揺れ、Q3 の差は最大 10 万 1,500 人になった。中央値 154.9 万人はどの定義でも 24 番目の県の値なので動かない。SPSS や Excel の QUARTILE.EXC が使う type6 は (n+1)p = 12, 36 がちょうど整数になるため 12 番目・36 番目の値そのものを返し、numpy と R の既定 type7 は 1 + (n−1)p = 12.5, 35.5 の位置を補間するのでずれる。他人の報告と四分位を突き合わせるときは、まず使ったソフトと定義を確かめる。

うまく動かないときは ①data/raw/SSDSE-B-2026.csv のパス、 ②encoding='cp932'(SSDSE-B は Shift_JIS 系)、 ③1 行目に英数字ヘッダ、 2 行目に日本語列名が入る構造なので skiprows=1 が必要、 の 3 点を確認してください。

🐍 scipy.stats.mstats.mquantiles — 9 流儀をまとめて扱う上級 API

SciPy には scipy.stats.mstats.mquantiles(x, alphap=, betap=) という関数があり、 α / β の値を 2 引数で直接指定できる。 9 流儀すべてを 1 API で実装できる利点があり、 専門書 (Hyndman & Fan, 1996) の公式実装に最も近い。

このコードでやること: SSDSE 47 県人口に対し、 scipy.stats.mstats.mquantiles で 6 種類の流儀 (R type 1 〜 9) の Q25/Q75 を一覧表示する。

📥 入力例(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
import pandas as pd
from scipy.stats import mstats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
pop = df.groupby('Prefecture')['A1101'].first().values

# Hyndman & Fan (1996) の type に対応する (alphap, betap)
# (0.4, 0.4) の Cunnane は R の type 1〜9 にない近似不偏の定義
types = {
    'type 6 (Weibull)'      : (0.0, 0.0),
    'type 5 (Hazen)'        : (0.5, 0.5),
    'Cunnane (not in R)'    : (0.4, 0.4),
    'type 7 (R/NumPy linear)': (1.0, 1.0),
    'type 8 (median unbiased)': (1/3, 1/3),
    'type 9 (normal unbiased)': (3/8, 3/8),
}
print(f'{"flavor":<24} {"Q25":>10} {"Q75":>10}')
for name, (a, b) in types.items():
    q = mstats.mquantiles(pop, prob=[0.25, 0.75], alphap=a, betap=b)
    print(f'{name:<24} {q[0]:>10.2f} {q[1]:>10.2f}')

📤 実行例:

flavor Q25 Q75 type 6 (Weibull) 1026000.00 2738000.00 type 5 (Hazen) 1030000.00 2687250.00 Cunnane (not in R) 1029200.00 2697400.00 type 7 (R/NumPy linear) 1034000.00 2636500.00 type 8 (median unbiased) 1028666.67 2704166.67 type 9 (normal unbiased) 1029000.00 2699937.50

💬 結果の読み方: SSDSE 47 県(人口 A1101、 単位は人)の Q25 は 1,026,000 〜 1,034,000 人、 Q75 は 2,636,500 〜 2,738,000 人で揺れる。 Q75 で約 10 万人 (3〜4%) の差。 サンプルサイズ n=47 と中程度のため流儀差が見えるが、 n=1000 以上では実用上同じ値になる。 「47 都道府県分析」のようなマイクロデータでは流儀を明示すること。

⚠️ 四分位の落とし穴(深掘り版・6件)

① 補間法(interpolation method)の違い

四分位の計算には9種類もの定義があり、 ライブラリによって値が違います。 numpy(デフォルト linear)、 pandas(linear)、 Excel(PERCENTILE.INC)、 R(type=7)、 SAS(type=3)など。 同じデータで値が 数%変わる ことも普通。 報告時は「numpy.percentile (interpolation='linear') で計算」のように明示する。 小サンプル(n < 20)では差が大きいので注意。

② IQR と SD の関係を盲信

正規分布では「IQR ≈ 1.349 × SD」という関係がありますが、 これは正規分布限定です。 裾の重い分布(t分布、 ラプラス分布等)や対数正規分布では関係が崩れる。 「IQR が大きい → SD も大きい」と即断せず、 必ず両方を計算して比較する。 また外れ値があると IQR は安定だが SD は爆発する、 という性質の違いも覚える。

③ Tukey の 1.5×IQR を機械的に「外れ値」と断定

Tukey の規則はあくまで探索的に注目すべき点を示す目安。 正規分布なら全データの 0.7% がフェンスを超えるので、 n = 1000 のデータなら 7 個程度は「外れ値判定」されて当然。 「フェンスを超えた = 異常」と即断して除外すると、 重要な情報を失います。 必ず散布図や原データに戻って、 文脈的に異常か判断する。

④ 多峰分布で IQR の意味が壊れる

双峰分布(ふた山)で IQR を計算すると、 「真ん中の谷」がIQRに含まれ、 「分布の広がり」を誤解しやすい。 例:「都市部 vs 郊外」で混合した家計データでは IQR が両群の差を反映してしまう。 必ずヒストグラム or KDE で分布の形を確認し、 必要なら群別に四分位を計算する。

⑤ 「Q2 = 中央値 = 平均」と思い込む

Q2 は中央値であって、 一般に平均と等しくありません。 対称分布では一致しますが、 右に裾を引く分布(所得・人口など)では「中央値 < 平均」が普通。 政策レポートで「世帯所得の中央値」と「平均世帯所得」を区別せずに使うと、 誤解を生む。 平均は外れ値の影響を強く受けるので、 中央値の方が「典型値」を表します。

⑥ サンプル数が極端に少ない時の不安定性

n = 5 のデータで「Q1 と Q3」を計算しても、 補間に意味がなく、 サンプルが 1 個変わるだけで値が大きく動く。 n < 10 では四分位より「全データの表示」が誠実。 また Q1/Q3 の標準誤差は中央値より大きいので、 信頼区間も併記する(ブートストラップ法など)。

⚠️ よくある落とし穴 — 四分位 で初学者がやりがちなミス

この用語を実務で使うときにつまずきやすい点を、 失敗パターン別に整理しました。 1 度経験すれば回避できるものばかりですが、 先に知っておくと事故が大幅に減ります。

❌ パーセンタイル法の違い
numpy.percentile の method 引数("linear", "lower", "midpoint")で値が変わる。
❌ 少数データの IQR
$n < 10$ では IQR の信頼性が低い。 ブートストラップで CI を。
❌ 「外れ値」を機械的に削除
$Q_3+1.5 \cdot IQR$ は便宜的なルール。 ドメイン知識で判断。
🛡 防御策まとめ:「適用条件の確認 → 適切な前処理 → 結果と前提のペア記述」の 3 ステップを習慣にすれば、 ここに挙げた失敗の大半は回避できます。

⚠️ 1.5×IQR 外れ値ルール — Tukey の境界を SSDSE で適用する

John Tukey (1977) が提案した古典的な外れ値検出ルールは 下限 = Q25 − 1.5×IQR、 上限 = Q75 + 1.5×IQR。 これを超える値を「mild outlier」、 さらに 3×IQR を超えるものを「extreme outlier」と呼ぶ。 正規分布なら全データの約 99.3 % が 1.5×IQR の範囲に収まる (片側 0.35% × 2)。

🔬 数式を言葉で読み解く — なぜ 1.5 か

正規分布における IQR は 1.349σ。 1.5 × 1.349σ ≒ 2.024σ なので、 下端 Q25 = μ−0.674σ から下に 2.024σ 引くと μ−2.698σ となり、 これは正規分布で約 0.35% に相当する位置。 つまり「真に外れ値である確率 0.7% 程度の閾値」として Tukey が経験的に選んだのが 1.5 という係数だ。 厳しめにするなら 3.0 (extreme)、 緩めるなら 1.0 (loose) を使う流儀もある。

このコードでやること: SSDSE-B-2026 の 47 県人口に Tukey 1.5×IQR ルールを適用し、 外れ値判定された県名と値を出力する。

📥 入力例(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
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
pop = df.groupby('Prefecture')['A1101'].first()

q1, q3 = np.quantile(pop, [0.25, 0.75])
iqr = q3 - q1
lower_mild, upper_mild = q1 - 1.5*iqr, q3 + 1.5*iqr
lower_ext,  upper_ext  = q1 - 3.0*iqr, q3 + 3.0*iqr

print(f'Q1={q1:.1f}  Q3={q3:.1f}  IQR={iqr:.1f}')
print(f'Mild fence : [{lower_mild:.1f}, {upper_mild:.1f}]')
print(f'Extreme    : [{lower_ext:.1f}, {upper_ext:.1f}]')

mild = pop[(pop < lower_mild) | (pop > upper_mild)]
extreme = pop[(pop < lower_ext) | (pop > upper_ext)]
print('\nMild outliers:')
print(mild.sort_values(ascending=False))
print('\nExtreme outliers:')
print(extreme.sort_values(ascending=False))

📤 実行例:

Q1=1034000.0 Q3=2636500.0 IQR=1602500.0 Mild fence : [-1369750.0, 5040250.0] Extreme : [-3773500.0, 7444000.0] Mild outliers: Prefecture 東京都 14086000 神奈川県 9229000 大阪府 8763000 愛知県 7477000 埼玉県 7331000 千葉県 6257000 兵庫県 5370000 福岡県 5103000 北海道 5092000 Name: A1101, dtype: int64 Extreme outliers: Prefecture 東京都 14086000 神奈川県 9229000 大阪府 8763000 愛知県 7477000 Name: A1101, dtype: int64

💬 結果の読み方: 47 県のうち上位 9 県が「mild outlier」、 上位 4 県が「extreme outlier」と判定される。 これは「東京・神奈川・大阪等の都市圏は他県と比べて統計的に異質」という直感を IQR で定量化した結果。 ただし「外れ値 = 削除」ではなく「外れ値 = 個別検討」が原則。 都道府県データのように母集団そのものなら「外れ値も含めて分析」が正しい姿勢。 1.5×IQR は探索的データ分析 (EDA) の最初のスクリーニング指標として用いる。

📊 グループ別四分位数 — 都道府県を地方ブロック別に分割

単一データに対する Q25/Q75 だけでなく、 「どんなグループに分けても四分位数の差が顕著か」を検定するのが groupby + quantile パターン。 SSDSE では地方ブロック (北海道・東北・関東・中部・近畿・中国・四国・九州沖縄) ごとの人口分布を見るのに使える。

このコードでやること: SSDSE-B-2026 を地方ブロック別にグループ化し、 各ブロックの人口の Q25/Q50/Q75 と IQR を一覧化する。

📥 入力例(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
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
pop = df.groupby('Prefecture')['A1101'].first().reset_index()

region_map = {
    '北海道':'北海道',
    '青森県':'東北','岩手県':'東北','宮城県':'東北','秋田県':'東北','山形県':'東北','福島県':'東北',
    '茨城県':'関東','栃木県':'関東','群馬県':'関東','埼玉県':'関東','千葉県':'関東','東京都':'関東','神奈川県':'関東',
    '新潟県':'中部','富山県':'中部','石川県':'中部','福井県':'中部','山梨県':'中部','長野県':'中部','岐阜県':'中部','静岡県':'中部','愛知県':'中部',
    '三重県':'近畿','滋賀県':'近畿','京都府':'近畿','大阪府':'近畿','兵庫県':'近畿','奈良県':'近畿','和歌山県':'近畿',
    '鳥取県':'中国','島根県':'中国','岡山県':'中国','広島県':'中国','山口県':'中国',
    '徳島県':'四国','香川県':'四国','愛媛県':'四国','高知県':'四国',
    '福岡県':'九州沖縄','佐賀県':'九州沖縄','長崎県':'九州沖縄','熊本県':'九州沖縄','大分県':'九州沖縄','宮崎県':'九州沖縄','鹿児島県':'九州沖縄','沖縄県':'九州沖縄',
}
pop['region'] = pop['Prefecture'].map(region_map)
pop['A1101'] = pop['A1101'] / 10000   # 単位を人 → 万人に

stats = pop.groupby('region')['A1101'].agg(
    n='size',
    q25=lambda s: s.quantile(0.25),
    median=lambda s: s.quantile(0.50),
    q75=lambda s: s.quantile(0.75),
    iqr=lambda s: s.quantile(0.75) - s.quantile(0.25),
)
print(stats.round(1))

📤 実行例:

n q25 median q75 iqr region 中国 5 65.0 129.8 184.7 119.7 中部 9 100.7 193.1 212.6 111.9 九州沖縄 8 108.2 136.8 158.9 50.7 北海道 1 509.2 509.2 509.2 0.0 四国 4 68.8 81.0 101.7 32.9 東北 6 106.0 117.4 162.1 56.1 近畿 7 135.1 172.7 395.2 260.1 関東 7 236.4 625.7 828.0 591.6

💬 結果の読み方: 関東 (IQR 591.6) と近畿 (IQR 260.1) は内部のバラつきが大きい (東京/大阪と他県の格差)。 四国・九州沖縄は IQR が小さく、 県間の差が比較的均質。 中央値で比べると関東 625.7 → 中部 193.1 → 東北 117.4 と段階的に減る。 「ブロック内の代表値 + ブロック内ばらつき」を 1 枚で把握できるのが groupby+quantile の威力。

⚠️ 四分位数の落とし穴 — 数式を言葉で読み解いた上で踏まないために

🎨 直感の深化 — 「4 等分する 3 本の線」で分布を掴む

四分位数のいちばん素朴なイメージは、 ソートしたデータを面積(個数)で 4 等分する 3 本の縦線です。 左から順に Q1(下側四分位数=下から 25%)、 Q2(中央値=50%)、 Q3(上側四分位数=75%)。 各区間にはデータのちょうど 1/4 ずつが入ります。 値そのものではなく順位で線を引くので、 いちばん大きい 1 個が 10 倍になっても Q1〜Q3 は 1 ミリも動かない——これが「頑健(ロバスト)」の正体です。

広がりは IQR=Q3−Q1 で測る。 これは「真ん中の 50% がどれだけの幅に収まっているか」。 標準偏差が全データの二乗和で決まるのに対し、 IQR は両端の 25% ずつを最初から無視するので、 外れ値に強い。 SSDSE-B-2026(2023 年・47 都道府県)の人口で実測すると、 Q1=103.4 万人 / Q2=154.9 万人 / Q3=263.6 万人、 IQR=160.2 万人。 東京都(1408.6 万人)を仮に 2 倍にしても Q1・Q2・Q3・IQR はすべて不変です。

🎯 3 つの覚え方

📝 補足(教材):「4 等分」という言葉から Q1・Q2・Q3 が等間隔だと誤解しがちですが、 それは左右対称な分布のときだけ。 人口のように右へ裾を引く分布では (Q3−Q2)=108.7 万人 ≫ (Q2−Q1)=51.5 万人 と右側が広い。 3 本の線の間隔の不揃いそのものが分布の歪みを語る、 と読むのが上級者の見方です。

⚠️ 落とし穴の深掘り補足 — 実測で見る「値がブレる」現実

「補間法で値が変わる」「小標本で不安定」は言葉だけだと軽く聞こえます。 ここでは SSDSE-B-2026 の実測値で、 どれくらいブレるのかを数字で示します(すべて 2023 年・A1101 人口・単位 万人)。

📐 同じ 47 県人口でも推定法 (type1–9) で Q1・Q3・IQR はこれだけ違う

Hyndman & Fan (1996) が整理した 9 つの分位数推定法を、 numpy.percentile(..., method=) の対応する名前でそのまま計算した実測結果です。 R の quantile(type=)、 Excel、 SAS はこのどれかに対応します。

typenumpy method 名Q1Q3IQR代表的な採用
1inverted_cdf102.6273.8171.2経験分布そのまま
3closest_observation102.6253.5150.9SAS 既定 (type=3)
4interpolated_inverted_cdf102.1258.6156.5—
5hazen103.0268.7165.7水文学で伝統的
6weibull102.6273.8171.2Excel PERCENTILE.EXC / Minitab
7linear103.4263.6160.2numpy / pandas / R / Excel.INC 既定
8median_unbiased102.9270.4167.6Hyndman-Fan 推奨
9normal_unbiased102.9270.0167.1正規分布で不偏

💬 読み方:IQR は最小 150.9(type3)から最大 171.2(type1/6)まで動き、 既定の linear(160.2)を基準にすると約 12.7% の幅があります。 「どの言語で計算したか」だけで報告値が 1 割ずれる、 という現実。 必ず method / type を明記し、 チーム内で 1 つに固定するのが唯一の防御策です(既定の linear=type7 が最も無難)。

📉 小標本の不安定性 — 東北 6 県で IQR が 4 倍ブレる実例

東北 6 県の人口(2023 年)は、 昇順で 91.4 / 102.6 / 116.3 / 118.4 / 176.7 / 226.4 万人(秋田・青森・岩手・山形・宮城・福島)。 この n=6 で Q1・Q3 を計算すると、 補間法だけで IQR が激変します。

methodQ1Q3IQR
lower102.6118.415.8
linear(既定)106.0162.156.1
higher116.3176.760.4

IQR が 15.8 〜 60.4 万人(約 4 倍)まで動きます。 47 県(n=47)では 1 割強の差だったものが、 n=6 では手が付けられないほど不安定に。 n が小さいほど四分位数は生データ 1 点の位置に強く引きずられるため、 n が二桁前半以下なら「四分位数を報告するより全データを見せる」方が誠実です。 どうしても幅を示したいときは ブートストラップで Q1・Q3 の信頼区間を添えます。

🔢 離散データ・同値の扱い(架空の最小例で確認)

架空の 5 段階満足度アンケート回答 [1, 1, 2, 2, 2, 3, 3, 4, 5](架空データ)を linear で計算すると Q1=2、 Q3=3、 IQR=1。 一方 lower でも Q1=2, Q3=3 と一致しますが、 回答が [3,3,3,3,3,3,4] のように同値が多いと Q1=Q2=Q3=3、 IQR=0 になります。 IQR=0 は「ばらつきゼロ」ではなく「中央 50% が同じ値」という意味。 リッカート尺度など離散データでは、 実在しない小数(例 2.75)を避けるため lower/higher/nearest を選ぶか、 度数分布そのものを併記するのが安全です。

🚀 発展 — 五数要約・ヒンジ・四分位偏差・分位点回帰

📊 五数要約と箱ひげ図

四分位数は単独で使うより、 最小値・Q1・中央値・Q3・最大値の 5 つをセットにした五数要約 (five-number summary)として扱うのが定石です。 SSDSE 人口なら 46.6(鳥取)/ 103.4 / 154.9 / 263.6 / 1408.6(東京)万人。 これをそのまま図にしたのが箱ひげ図で、 箱の両端が Q1・Q3、 箱の中の線が中央値、 ヒゲの先が Tukey フェンス、 その外の点が外れ値候補。 df.describe() が出す 8 行のうち 5 行はこの五数要約です。 → 箱ひげ図

🔧 ヒンジ (hinge) と Tukey の元祖流儀

Tukey (1977) が箱ひげ図を作ったとき使ったのは、 厳密な「四分位数」ではなくヒンジ (lower/upper hinge)という近縁量でした。 中央値でデータを半分に割り、 各半分の中央値をヒンジとする——手計算しやすい定義です。 現代の numpy/pandas の四分位数(linear=type7)とは値が微妙に違い、 これも「実装で値が変わる」一因。 R の fivenum() はこのヒンジ流儀(type に近い挙動)を返すため、 quantile() の結果と食い違うことがあります。

📐 四分位偏差 (quartile deviation) と分布の歪み

四分位偏差 QD=(Q3−Q1)/2=IQR/2。 人口データでは 80.1 万人。 標準偏差の頑健版として、 中央値と組で「中央値 ± QD」のように使えます。 さらに 3 点の間隔比から歪みも読めます:四分位歪度 (Bowley skewness) = ((Q3−Q2)−(Q2−Q1)) / (Q3−Q1)。 人口では (108.7−51.5)/160.2 ≒ +0.36 と正で、 右へ裾を引く分布を順位ベースだけで定量化できます(平均や標準偏差を一切使わない歪度指標)。

📈 分位点回帰 (quantile regression)

四分位数の考え方を回帰に持ち込んだのが分位点回帰。 通常の最小二乗回帰が「説明変数を固定したときの平均」を推定するのに対し、 分位点回帰は「Q1 の線」「中央値の線」「Q3 の線」を別々に引きます。 所得のように分布の裾で挙動が違うデータで威力を発揮し、 外れ値にも頑健。 → 分位点回帰

🔗 推定法をまとめて扱う実装

上の type1–9 を一括で試すには numpy.percentile(x, [25,75], method=名) を回すか、 scipy.stats.mstats.mquantiles(x, alphap, betap) で α, β を直接指定します(このページの Python セクションに実行例あり)。 ロバスト統計の観点では、 四分位ベースの散らばりに加えて MAD(中央絶対偏差) も併用すると分布の性質を多面的に掴めます。

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

四分位数 (Quartile) 前提: 順序統計量 並列: 五数要約 / IQR 発展: 10 分位 / 5 分位 応用: 箱ひげ図 対比: 平均 ± SD 統合: 記述統計

Q1: 何を知りたい?

Q2: データの種類は?

Q3: サンプルサイズは?

Q4: 仮定は?

📏 効果量の参照表

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

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

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

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

📍 体系階層のパス

🌐 統計・データサイエンス › 記述統計 › ばらつき › 四分位

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

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

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

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

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

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

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

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

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

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

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

🔗 隣接手法への橋渡し

「四分位数」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。

SSDSE-B-2026 の都道府県人口を四分位点で要約すると、 Q1 ≈ 103 万・Q2 (中央値) ≈ 155 万・Q3 ≈ 264 万、 上位 25% は急に伸びる右裾分布だと一目で分かる。

🌳 手法選択フロー

「quartile」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。

典型シナリオ別の手法選択

シナリオ重視する観点候補手法
分布が左右対称・正規に近い平均±標準偏差で十分四分位は概観として併用
外れ値が多い / 歪んだ分布 (人口・所得)頑健な中心と散らばりが必要四分位 Q1/Q2/Q3 と IQR を主指標に
複数群を比較したい群間の散らばりを一目で見たい箱ひげ図 (四分位を可視化)
外れ値を機械的に検出したいTukey ルールが標準Q1-1.5×IQR / Q3+1.5×IQR の外を外れ値
学生の成績順位を扱う上位 25% / 中位 50% / 下位 25%四分位順位を直接使用
47 都道府県の散らばりを見るSSDSE-B-2026 で歪み大Q1/Q2/Q3 + IQR で要約

選んだ後の検証ステップ

  1. 分布形状確認: ヒストグラムや箱ひげ図で歪度・尖度を見て、 四分位による要約が代表的かを確認
  2. Q1 / Q3 算出方法: numpy.percentile の interpolation オプション (linear / lower / midpoint) によって値が変わるため、 採用した方法を明記
  3. IQR と外れ値判定: Q1−1.5·IQR / Q3+1.5·IQR を境界に外れ値を抽出し、 妥当性を分野知識と照合
  4. サンプル数依存性: n < 20 では四分位の推定誤差が大きい。 ブートストラップで Q1 / Q3 の信頼区間を確認
  5. 解釈: SSDSE-B-2026 都道府県データで Q1 / Q3 を出し、 中央 50% に収まる県が分野知識的に妥当かを検討

🔖 キーワード索引(深掘り版)

論文・記事に登場する用語のリンクで該当箇所へジャンプ:

🧮 SSDSE 実値計算 ⚠️ 落とし穴 6選 🐍 Python バリエーション 🔗 関連用語 IQR Tukey fence 箱ひげ図 補間法